今天教大家实现一个有意思的小游戏——三子棋
在实现之前应该先了解三子棋的规则,方便去更好的实现。
三子棋的规则如下:
- 棋盘呈横三行列,纵三列分布,为九宫格样式
- 双方的棋子一般以不同的形状来区分
- 双方轮流在格子里摆放棋子,先连成三棋一线者视为胜利
- 棋盘被摆满棋子仍未分出胜利,视为平局
接下来将围绕这些规则,将这些规则一一实现。
一·
最开始应将菜单先打印出,让玩家有选择,菜单的设计不必过于复杂,写一个函数就行
void menu()
{
printf("*******************\n");
printf("*****1 三子棋******\n");
printf("*****0 退出游戏****\n");
printf("*******************\n");
}
之后就是实现棋盘
void DisplayBoard(char board[hang][lie], int x, int y)
{
int i = 0, j = 0;
for (i = 0; i < x; i++)
{
for (j = 0; j < y; j++)
{
printf(" %c ", board[i][j]);
if (j < y - 1)
printf("|");
}
printf("\n");
if (i < x - 1)
{
for (j = 0; j < y; j++)
{
printf("---");
if (j < y - 1)
printf("|");
}
}
printf("\n");
}
}
要考虑的是如何将数组中的元素分开,以什么方式分开,用什么分开,也可以不按照例子这样分开元素,明白其中的逻辑就可以随意变化
之后就是区分棋子,用两个不同的符号就行,例子里用的是
玩家:*
电脑:#
将棋子的信息存在数组里,方便后续实现玩法,创建了一个数组之后要将这个数组里的元素全部变为空格,这样在输出的过程中不会将未下的位置显示出来,
void InitBoard(char board[hang][lie], int x,int y)
{
int i = 0,j = 0;
for (i = 0; i < x; i++)
{
for (j = 0; j < y; j++)
board[i][j] = ' ';
}
}
开始双方下棋
玩家下棋:
void PlayerMove(char board[hang][lie], int h , int l)
{
int x = 0, y = 0;
printf("玩家下棋\n");
while (1)
{
printf("请输入要下棋的坐标:>");
scanf("%d %d", &x, &y);
if (x >= 1 && x <= hang && y >= 1 && y <= lie)
{
if (board[x-1][y-1] == ' ')
{
board[x-1][y-1] = '*';
break;
}
else
printf("该位置已占用,请重新输入\n");
}
else
printf("输入错误,请重新输入");
}
}
先输出提示玩家下棋,会有以下情况,玩家输入正确坐标和已经被占用的坐标已经错误坐标,分别用if——else语句将这3中情况表达出来
电脑下棋
void ComputerMove(char board[hang][lie], int x, int y)
{
printf("电脑下棋\n");
while (1)
{
x = rand() % hang;
y = rand() % lie;
if (board[x][y] == ' ')
{
board[x][y] = '#';
break;
}
}
}
电脑下棋的逻辑比较简单,用rand配合srand创造出随机数,通过%行数和列数使产生随机数在正确的范围,通过while循环如果随机数对应的位置上没有被占用就将该位置赋值为#,然后跳出循环,
(rand和srand具体用法请上网查询)
最后就是判断输赢
static int IsFull(char board[hang][lie], int x, int y)
{
int i = 0, j = 0;
for (i = 0; i < hang; i++)
{
for (j = 0; j < lie; j++)
{
if (board[i][j] == ' ')
return 0;
}
}
return 1;
}
char IsWin(char board[hang][lie], int x, int y)
{
int i = 0, j = 0,count=0;
for (i = 0; i < hang - 1; i++)
{
count = 0;
for (j = 0; j < hang - 1; j++)
{
if (board[i][j] == board[i][j + 1] && board[i][j] != ' ')
count++;
if (count == hang - 1)
return board[i][j];
}
}
for (j = 0; j < lie - 1; j++)
{
count = 0;
for (i = 0; i < lie- 1; i++)
{
if (board[i][j] == board[i+1][j] && board[i][j] != ' ')
count++;
if (count == lie - 1)
return board[i][j];
}
}
count = 0;
for (i = 0,j=0; i < hang - 1; i++,j++)
{
if (board[i][j] == board[i + 1][j + 1] && board[i][j] != ' ')
count++;
if (count == hang - 1)
return board[i][j];
}
count = 0;
for (i = 0, j = lie - 1; i < hang - 1, j>0; i++, j--)
{
if (board[i][j] == board[i + 1][j - 1] && board[i][j] != ' ')
count++;
if(count==hang-1)
return board[i][j];
}
if (IsFull(board, x, y))
return 'Q';
return 'C';
}
判断输赢的逻辑比较复杂
一共是4种情况(i表示行,j表示列)
- 3个相同棋子横着摆放,判断逻辑为让行数不变(即i不变),让列数+1(j+1)判断前一个与后一个是否相等,并且已经被占用
- 3个相同棋子竖着摆放,也是同理,让i+1,j不变其他与情况1相同
- 对角线,让i和j都+1其他与情况1相同
- 反对角线,让i+1,j-1其他与情况1相同
平局的逻辑比较简单,就是遍历数组所有元素,如果有空格,说明没被占满,如果没有就是平局。
代码运行的逻辑
void game()
{
srand((unsigned int)time(NULL));
char x = 0;
char board[hang][lie] = { 0 };
InitBoard(board, hang, lie);
DisplayBoard(board, hang, lie);
while (1)
{
PlayerMove( board,hang,lie);
DisplayBoard(board,hang ,lie);
x = IsWin(board, hang, lie);
if (x != 'C')
break;
ComputerMove(board, hang, lie);
DisplayBoard(board, hang, lie);
x = IsWin(board, hang, lie);
if (x != 'C')
break;
}
if (x == '*')
printf("玩家赢\n");
else if (x == '#')
printf("电脑赢\n");
else
printf("平局\n");
}
通过iswin函数的返回值进行判断对应着3种情况:玩家赢,电脑赢,平局。
小提示:宏不能充当变量名。