C語言數組應用實現三子棋遊戲

三子棋遊戲的基本構架是數組的應用,但是要實現遊戲還得結合具有相關功能的函數,接下來就介紹三子棋遊戲的基本框架及相關函數:
下面先介紹一下寫三子棋代碼的過程和思路:

1、遊戲開始要先顯示遊戲界面 (菜單函數)
2、要有一個棋盤給玩傢下棋,所以需要一個二維數組,最開始顯示給玩傢的棋盤應該是空棋盤,所以初始化數組為空格(棋盤初始化函數) ,全為空格的數組打印出來是沒有顯示的,所以我們要畫一個棋盤框並把它打印出來(打印棋盤函數)
3、開始遊戲後,玩傢下棋(玩傢下棋函數) ,數組更改並打印,電腦下棋(電腦下棋函數) ,數組更改並打印。
4、遊戲是一個循環的過程,所以輸贏(判斷輸贏函數)及平局(判斷平局函數)的判斷也是一個循環的過程,因此判斷輸贏及平局應該在下每一顆棋子後就進行判斷。

來看一下遊戲效果:

程序運行,顯示遊戲菜單,選擇1開始遊戲。

玩傢落子為x,電腦落子為0。

這裡的棋盤行和列用宏定義可以方便更改:

#define ROW 3
#define COL 3 

頭文件game.h:

#define _CRT_SECURE_NO_WARNINGS 1
#include<stdio.h>
#include<stdlib.h>
#include<time.h>
#define ROW 3
#define COL 3
void setboard(char arr[ROW][COL], int row, int col);
void displayboard(char arr[ROW][COL], int row, int col);
void playermove(char arr[ROW][COL], int row, int col);
void computermove(char arr[ROW][COL], int row, int col);
int iswin(char arr[ROW][COL], int row, int col);
int isfull(char arr[ROW][COL], int row, int col);
void menu();

源文件main.c:

  • 按照前面的分析及思路寫出框架,完善函數功能,構成體系;
  • 人機對戰中電腦下棋是隨機的;
  • 需要註意在每次落子後都要判斷輸贏平局;
#define _CRT_SECURE_NO_WARNINGS 1
//三子棋主函數
#include "game.h"
int main()
{
 srand((unsigned int)time(NULL));
  //遊戲界面
 int x = 0;
 int ret = 0;
 char n = 0;
 while(1)
 {
  menu();//菜單
  scanf("%d", &x);
  printf("\n");
  if (x == 1)
  {
   //設置棋盤
   char arr[ROW][COL] = { 0 };
   setboard(arr, ROW, COL);//棋盤初始化為空格
   displayboard(arr, ROW, COL);//打印棋盤
   while (1)
   {
    //玩傢下棋
    playermove(arr, ROW, COL);
    //打印棋盤
    displayboard(arr, ROW, COL);
    //判斷平局
    ret = isfull(arr, ROW, COL);
    if (ret == 1)
    {
     printf("平局\n");
     break;
    }
    //判斷輸贏
    n = iswin(arr, ROW, COL);
    if (n == 'x')
    {
     printf("玩傢贏\n");
     break;
    }
    else if (n == '0')
    {
     printf("電腦贏\n");
     break;
    }
    //玩傢贏--x
    //電腦贏--0
    //平局--P
    //繼續--C
    
    //電腦下棋
    computermove(arr, ROW, COL);
    //打印棋盤
    displayboard(arr, ROW, COL);
    //判斷平局
    ret = isfull(arr, ROW, COL);
    if (ret == 1)
    {
     printf("平局\n");
     break;
    }
    //判斷輸贏
    n = iswin(arr, ROW, COL);
    if (n == 'x')
    {
     printf("玩傢贏\n");
     break;
    }
    else if (n == '0')
    {
     printf("電腦贏\n");
     break;
    }
   }
  } 
 else if (x == 0)
   break;
 else
 printf("輸入錯誤,請重新輸入!\n");
 
 }
 system("pause");
 return 0;
}

源文件game.c:

主要的函數有以下幾個:
(菜單函數沒什麼可講的)

  • 初始化棋盤
void setboard(char arr[ROW][COL], int row, int col)
{
 int i = 0;
 int j = 0;
 for (i = 0; i < ROW; i++)//棋盤初始化為空格
 {
  for (j = 0; j < COL; j++)
  {
   arr[i][j] = ' ';
  }
  
 }
}
  • 打印棋盤

這裡我加瞭格子的序號,提高使用感,在大於3小於10的棋盤中可以更好的找到想要的坐標,為什麼小於10呢,因為在序號由一位數變為兩位數時,打印出來的棋盤不規整瞭,當然這個地方還可以優化,目前就隻支持行列小於10的棋盤。

void displayboard(char arr[ROW][COL], int row, int col)
{
 int i = 0;
 int j = 0;
 
 for (i = 1; i <= col; i++)
 {
  printf("  %d  ", i);
  if (i < COL )
   printf("|");
 }
 printf("\n");
 for (j = 0; j < COL ; j++)
 {
  if (j == 0)
  {
   printf(" ----");
  }
  else if (j > 0)
  {
   printf("-----");
  }
  if (j < COL - 1)
   printf("|");
 }
 printf("\n");
 
 for (i = 0; i < ROW; i++)
 {
  printf("%d ", i + 1);
  for(j = 0; j < COL; j++)
  { 
   if (j == 0)
   {
    printf(" %c ", arr[i][j]);
   }
   else
   {
    printf("  %c  ", arr[i][j]);
   }
   
   if(j < COL - 1)
      printf("|");
  }
  printf("\n");
  if(i < ROW-1)
  { 
   for (j = 0; j < COL; j++)
   {
    if (j == 0)
    {
     printf(" ----");
    }
    else if (j > 0)
    {
     printf("-----");
    }
    if (j < COL - 1)
     printf("|");
   }
   printf("\n");
  }

 }
 
} 
  • 玩傢下棋

這裡要註意判斷坐標的合法性

void playermove(char arr[ROW][COL], int row, int col)
{
 printf("\n\n玩傢走:>\n");
 while (1)
 {
  printf("請輸入坐標:>");
  int x = 0;
  int y = 0;
  scanf("%d%d", &x, &y);
  if (x > 0 && x <= ROW && y > 0 && y <= COL && arr[x-1][y-1] == ' ')
  {
   arr[x-1][y-1] = 'x';
   break;
  }
  else if (x > ROW || y > COL)
  {
   printf("錯誤坐標,請重新輸入!\n");
  }
  else if (arr[x-1][y-1] != ' ')
  {
   printf("該坐標下過棋瞭,請重新輸入!\n");
  }
  
 }
 
}
  • 電腦下棋

電腦下棋是隨機的,利用rand();及srand();產生0-2的隨機數,註意生成隨機數需要引用time.h這個頭文件,雖然是產生隨機坐標但是要確定電腦找到一個有空位的棋格才可以停下。

void computermove(char arr[ROW][COL], int row, int col)
{
 printf("\n\n電腦走:>\n");
 int x = 0;
 int y = 0;
 while (1)
 {
  x = rand() % ROW;
  y = rand() % COL;
  if (arr[x][y] == ' ')
  {
   arr[x][y] = '0';
   break;
  }
 }
 
}
  • 判斷平局
int isfull(char arr[ROW][COL], int row, int col)
{
 int x = 0;
 int y = 0;
 for (x = 0; x < row; x++)
 {
  for (y = 0; y < col; y++)
  {
   if (arr[x][y] == ' ')
    return 0;
  }
 }
 return 1;
}
  • 判斷輸贏

隻要棋盤中任意一個坐標的行,列,斜為相同符號,即為勝利,我這裡在保證坐標合法的前提下對每一個坐標周圍8個坐標進行判斷,這樣可以做到在非3×3的棋盤中也可以完成三子棋遊戲,當然這段代碼隻是實現瞭功能而已,寫的非常繁瑣,我也覺得非3×3裡還下三子棋說不過去,之後也可以繼續擴展到五子棋的判斷輸贏,以後再詳細整改。

int  iswin(char arr[ROW][COL], int row, int col)
{
 int x = 0; 
 int y = 0;
 int count = 0;
 
 
 for (x = 0; x < row; x++)
 {
  for (y = 0; y < col; y++)
  {
  
   if (arr[x][y] == arr[x][y - 1] && arr[x][y - 1] == arr[x][y + 1] && arr[x][y] != ' '&& arr[x][y-1] != ' '&& arr[x][y+1] != ' ')
   {
    return arr[x][y];
   }
   else if (arr[x][y] == arr[x - 1][y + 1] && arr[x - 1][y + 1] == arr[x + 1][y - 1] && arr[x][y] != ' '&& arr[x-1][y+1] != ' '&& arr[x+1][y-1] != ' ')
   {
    return arr[x][y];
   }
   else if(arr[x][y] == arr[x - 1][y] && arr[x - 1][y] == arr[x + 1][y] && arr[x][y] != ' '&& arr[x-1][y] != ' '&& arr[x+1][y] != ' ')
   {
    return arr[x][y];
   }
   else if (arr[x][y] == arr[x - 1][y - 1] && arr[x - 1][y - 1] == arr[x + 1][y + 1] && arr[x][y] != ' '&& arr[x-1][y-1] != ' '&& arr[x+1][y+1] != ' ')
   {
    return arr[x][y];
   }
  }
 }
}

以上就是我的代碼,寫完以後還有些小遺憾,很多地方沒有處理好,希望各位能幫我優化改進。

希望本文對大傢的學習有所幫助,也希望大傢多多支持WalkonNet。

推薦閱讀: