一、游戏规则
三子棋是一种民间传统游戏,又叫九宫棋,顾名思义,棋盘为3X3的九宫格。
玩法:电脑和玩家双方轮流交替下棋,只要任意一方的棋子有三个连在一起,可以为横连、纵连或斜连,则该方获胜,游戏结束。若棋盘满了,则判定为平局。
二、设计思路
1.定义棋盘,初始化并打印
代码如下(示例):
#define ROW 3 //行
#define COL 3 //列
#define ROWS ROW+1
#define COLS COL+1
//test.c中定义棋盘
char show[ROWS][COLS];
//初始化棋盘
void InitBoard(char (*arr)[COLS], int rows, int cols, char set)
{
int i = 0;
int j = 0;
for (i = 0; i < rows; i++)
{
for (j = 0; j < cols; j++)
{
arr[i][j] = set;
}
}
}
//打印棋盘
void DisplayBoard(char(*arr)[COLS], int row, int col)
{
int i = 0;
int j = 0;
printf(" 1 2 3\n");
for (i = 1; i <= row; i++)
{
printf(" %d ", i);
for (j = 1; j <= col; j++)
{
printf("|");
printf(" %c ", arr[i][j]);
}
printf("|\n");
printf(" |---|---|---|\n");
}
}
效果如图所示:
2.游戏过程
游戏步骤:
打印棋盘 → 玩家走一步 → 电脑走一步 → 判定输赢 or 平局
a. 游戏开始:
void Play(char(*arr)[COLS], int row, int col)
{
int win = 0;
while (IsWin(arr, row, col) == ' ')
{
PlayerPlay(arr, row, col);//玩家走一步
if (IsWin(arr, row, col) != ' ')//判断游戏是否结束
break;
ComputerPlay(arr, row, col);//电脑走一步
if (IsWin(arr, row, col) != ' ')//判断游戏是否结束
break;
}
if (IsWin(arr, row, col) == 'O')
printf("玩家赢!游戏结束!\n");
else if (IsWin(arr, row, col) == 'X')
printf("电脑赢!游戏结束!\n");
else if (IsWin(arr, row, col) == 'P')
printf("平局!游戏结束!\n");
}
b. 玩家下棋:
玩家每次输入要下的位置坐标(i,j),在得到(i,j)坐标后我们需要对其进行判断来保证该坐标在棋盘内并且该坐标处没有下过棋,否则,我们需要让玩家输入现代新的坐标。
//玩家下棋
void PlayerPlay(char(*arr)[COLS], int row, int col)
{
int i;
int j;
printf("玩家请下棋:>");
scanf("%1d%1d", &i, &j);
if (i >= 1 && i <= row && j >= 1 && j <= col && arr[i][j] == ' ')
{
arr[i][j] = 'O';
DisplayBoard(arr, row, col);
}
else
{
printf("坐标有误,请重新输入!\n");
PlayerPlay(arr, row, col);
}
}
c. 电脑下棋:
电脑是通过生成随机的坐标来下棋的,在每次生成随机的(x,y)时需要判定(x,y)点是否已经下过棋了,如果该点已经下过棋了,需要生成新的(x,y)坐标。需要注意的是,每次电脑必须下一个棋,所以这里我通过while( )循环来控制下棋的次数。
//电脑下棋
void ComputerPlay(char(*arr)[COLS], int row, int col)
{
printf("电脑请下棋:>\n");
int count = 1;
while (count)
{
int i = rand() % row + 1;
int j = rand() % col + 1;
if (arr[i][j] == ' ')
{
arr[i][j] = 'X';
DisplayBoard(arr, row, col);
count--;
}
}
}
d. 判定输赢 or 平局
判定规则:只要任意一方的棋子有三个连在一起,可以为横连、纵连或斜连,则该方获胜,游戏结束。若棋盘满了,则判定为平局。
//判断棋盘是否满了
int IsFull(char arr[ROW][COL], int row, int col)
{
int i = 0;
int j = 0;
for (i = 1; i<=row; i++)
{
for (j = 1; j<=col; j++)
{
if (arr[i][j] == ' ')
return 0;
}
}
return 1;
}
//横竖斜有三个相同的棋子相连即为赢
//棋盘满了还没有分出胜负即为平局
char IsWin(char arr[ROWS][COLS], int row, int col)
{
int i = 0;
int j = 0;
for (i = 1; i<=row; i++)//横连
{
if (arr[i][1] == arr[i][2] && arr[i][2] == arr[i][3])
return arr[i][1];
}
for (j = 1; j<=col; j++)//竖连
{
if (arr[1][j] == arr[2][j] && arr[2][j] == arr[3][j])
return arr[1][j];
}
if ((arr[1][1] == arr[2][2] && arr[2][2] == arr[3][3]) || (arr[1][3] == arr[2][2] && arr[2][2] == arr[3][3]))//斜连
return arr[1][1];
else if (IsFull(arr, row, col)) //棋盘满了即为平局
return 'P';
else
return ' '; //返回’ ’说明游戏没有结束,还可以继续玩
}
注意:
在判断三个棋子是否相等时,
我们不能用连等(arr[1][1] == arr[2][2] == arr[3][3])来判断,
而是应该用两两相等(arr[1][1] == arr[2][2] && arr[2][2] == arr[3][3]),
这是因为 == 是从左到右进行运算的,对于表达式(arr[1][1] == arr[2][2] == arr[3][3]),首先会进行(arr[1][1] == arr[2][2])的逻辑运算然后得出逻辑值1或0,得到的结果作为返回值进行(1或0==arr[3][3])的逻辑运算,然后得出逻辑值1或0,作为整个表达式的返回值。
到这里游戏大体就设计好了,下面我们为游戏写一个简单的菜单和测试游戏的代码:
#include "game.h"
void menu()
{
printf("****************************\n");
printf("***** 三子棋小游戏 *****\n");
printf("********* 1.play *********\n");
printf("********* 0.exit *********\n");
printf("****************************\n");
}
void game()
{
//定义棋盘
char show[ROWS][COLS];
//初始化棋盘
InitBoard(show, ROWS, COLS, ' ');
//打印棋盘
DisplayBoard(show, ROW, COL);
//下棋
Play(show, ROW, COL);
}
void test()
{
int choice = 0;
srand((unsigned int)time(NULL));
do
{
menu();
printf("请输入:>");
scanf("%d", &choice);
switch (choice)
{
case 1:
game();
break;
case 0:
printf("********* 再见 *********\n");
break;
default:
printf("输入有误,请重新输入!\n");
break;
}
} while (choice);
}
int main()
{
test();
return 0;
}
三、效果展示
四、源代码
game.h:
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#define ROW 3
#define COL 3
#define ROWS ROW+1
#define COLS COL+1
//初始化棋盘
void InitBoard(char arr[ROWS][COLS], int rows, int cols, char set);
//打印棋盘
void DisplayBoard(char arr[ROWS][COLS], int row, int col);
//下棋
void Play(char(*arr)[COLS], int row, int col);
void PlayerPlay(char(*arr)[COLS], int row, int col);//玩家下棋
void ComputerPlay(char(*arr)[COLS], int row, int col);//电脑下棋
//判断输赢or平局
char IsWin(char arr[ROWS][COLS], int row, int col);
test.c:
#include "game.h"
void menu()
{
printf("****************************\n");
printf("***** 三子棋小游戏 *****\n");
printf("********* 1.play *********\n");
printf("********* 0.exit *********\n");
printf("****************************\n");
}
void game()
{
//定义棋盘
char show[ROWS][COLS];
//初始化棋盘
InitBoard(show, ROWS, COLS, ' ');
//打印棋盘
DisplayBoard(show, ROW, COL);
//下棋
Play(show, ROW, COL);
}
void test()
{
int choice = 0;
srand((unsigned int)time(NULL));
do
{
menu();
printf("请输入:>");
scanf("%d", &choice);
switch (choice)
{
case 1:
game();
break;
case 0:
printf("********* 再见 *********\n");
break;
default:
printf("输入有误,请重新输入!\n");
break;
}
} while (choice);
}
int main()
{
test();
return 0;
}
game.c:
#include "game.h"
void InitBoard(char (*arr)[COLS], int rows, int cols, char set)
{
int i = 0;
int j = 0;
for (i = 0; i < rows; i++)
{
for (j = 0; j < cols; j++)
{
arr[i][j] = set;
}
}
}
void DisplayBoard(char(*arr)[COLS], int row, int col)
{
int i = 0;
int j = 0;
printf(" 1 2 3\n");
for (i = 1; i <= row; i++)
{
printf(" %d ", i);
for (j = 1; j <= col; j++)
{
printf("|");
printf(" %c ", arr[i][j]);
}
printf("|\n");
printf(" |---|---|---|\n");
}
}
void PlayerPlay(char(*arr)[COLS], int row, int col)
{
int i;
int j;
printf("玩家请下棋:>");
scanf("%1d%1d", &i, &j);
if (i >= 1 && i <= row && j >= 1 && j <= col && arr[i][j] == ' ')
{
arr[i][j] = 'O';
DisplayBoard(arr, row, col);
}
else
{
printf("坐标有误,请重新输入!\n");
PlayerPlay(arr, row, col);
}
}
void ComputerPlay(char(*arr)[COLS], int row, int col)
{
printf("电脑请下棋:>\n");
int count = 1;
while (count)
{
int i = rand() % row + 1;
int j = rand() % col + 1;
if (arr[i][j] == ' ')
{
arr[i][j] = 'X';
DisplayBoard(arr, row, col);
count--;
}
}
}
//判断棋盘是否满了,没有空位即为满了
int IsFull(char arr[ROW][COL], int row, int col)
{
int i = 0;
int j = 0;
for (i = 1; i<=row; i++)
{
for (j = 1; j<=col; j++)
{
if (arr[i][j] == ' ')
return 0;
}
}
return 1;
}
//定义赢和平局的规则,横竖斜有三个相同的棋子相连即为赢
char IsWin(char arr[ROWS][COLS], int row, int col)
{
int i = 0;
int j = 0;
for (i = 1; i<=row; i++)//横连
{
if (arr[i][1] == arr[i][2] && arr[i][2] == arr[i][3])
return arr[i][1];
}
for (j = 1; j<=col; j++)//竖连
{
if (arr[1][j] == arr[2][j] && arr[2][j] == arr[3][j])
return arr[1][j];
}
if ((arr[1][1] == arr[2][2] && arr[2][2] == arr[3][3]) || (arr[1][3] == arr[2][2] && arr[2][2] == arr[3][3]))//斜连
return arr[1][1];
else if (IsFull(arr, row, col)) //棋盘满了即为平局
return 'P';
else
return ' ';
}
void Play(char(*arr)[COLS], int row, int col)
{
int win = 0;
while (IsWin(arr, row, col) == ' ')
{
PlayerPlay(arr, row, col);
if (IsWin(arr, row, col) != ' ')
break;
ComputerPlay(arr, row, col);
if (IsWin(arr, row, col) != ' ')
break;
}
if (IsWin(arr, row, col) == 'O')
printf("玩家赢!游戏结束!\n");
else if (IsWin(arr, row, col) == 'X')
printf("电脑赢!游戏结束!\n");
else if (IsWin(arr, row, col) == 'P')
printf("平局!游戏结束!\n");
}