前言:
三子棋是一种民间传统游戏,又叫九宫棋、圈圈叉叉棋、一条龙、井字棋等。游戏规则是双方对战,双方依次在9宫格棋盘上摆放棋子,率先将自己的三个棋子走成一条线就视为胜利。但因棋盘太小,三子棋在很多时候会出现和棋的局面。
设计思路:
先开一个test.c文件用来进行游戏的逻辑测试,再开一个game.h头文件和game.c文件分别用来进行函数声明和实现游戏的逻辑,然后就是打印菜单、生成棋盘、实现玩家下棋、实现电脑下棋、判断游戏的输赢、游戏优化。
1. 打印菜单
test.c
void menu()
{
printf("***************************\n");
printf("******** 1.play ********\n");
printf("******** 2.exit ********\n");
printf("***************************\n");
}
int main()
{
int input = 0;
do
{
menu();
printf("请选择>:");
scanf("%d", &input);
switch (input)
{
case 1:
game();
break;
case 0:
printf("退出游戏.\n");
break;
default:
printf("输入有误,请重新输入.\n");
}
} while (input);
return 0;
}
2. 生成棋盘
2.1 初始化棋盘
我们可以用空格将每一个格子初始化。
test.c文件:
board[ROW][COL] = { 0 };
InitBoard(board, ROW, COL);
game.c文件:
void InitBoard(char board[ROW][COL], int row, int col)
{
for (int i = 0; i < row; i++)
{
for (int j = 0; j < col; j++)
{
board[i][j] = " ";
}
}
}
其中的ROW和COL是两个宏定义。
game.h
#define ROW 3
#define COL 3
2.2 打印棋盘
打印棋盘时我们可以一些符号隔开不同的空格,这样就会使我们的棋盘更加美观。比如我们可以使用“|”将同一行的空格分开,用“-”将不同行的空格分开,这样我们就可以得到一个如下的九宫格了。
game.c文件:
void DisplayBoard(char board[ROW][COL], int row, int col)
{
for (int i = 0; i < row; i++)
{
for (int j = 0; j < col; j++)
{
printf(" ");
if (j < col - 1)
{
printf("|");
}
}
printf("\n");
if (i < row - 1)
{
for (int j = 0; j < col; j++)
{
printf("---");
if (j < col - 1)
printf("|");
}
printf("\n");
}
}
}
3. 实现玩家下棋和电脑下棋
为了游戏的可实行性,当玩家或电脑下完一个棋子后我们需要考虑以下两点:
1.玩家或电脑所下的坐标是否在棋盘的范围内。
2.玩家或电脑所下的位置是否已经被下过棋子了。
依据上面的两点条件的我们需要分别写一个条件语句,判断玩家是否合法下棋。
3.1 玩家下棋
game.c文件:
void PlayerMove(char board[ROW][COL], int row, int col)
{
int x = 0, y = 0;
printf("玩家下棋:\n");
while (1)
{
printf("请输入你要落子的坐标:");
scanf("%d%d", &x, &y);
if (x >= 1 && x <= row && y >= 1 && y <= col)
{
if (board[x - 1][y - 1] == ' ')
{
board[x - 1][y - 1] = '*';
break;
}
else
{
printf("输入的坐标已被占用,请重新输入\n");
}
}
else
{
printf("坐标非法,请重新输入\n");
}
}
}
3.2 电脑下棋
思路:
我们可以在让电脑生成随机数,这样就可以使其随机生成一个坐标下棋子,那么我们就可以简单的实现电脑下棋的效果了。
随机数的生成则可以使用rand函数、srand函数以及time函数。
game.c文件:
void ComputerMove(char board[ROW][COL], int row, int col)
{
printf("电脑下棋:>\n");
while (1)
{
int x = rand() % row;
int y = rand() % row;
if (x <= row && x >= 1 && y <= row && y >= 1)
{
if (board[x][y] == ' ')
{
board[x][y] = '#';
break;
}
}
}
}
test.c文件:
srand((unsigned int)time(UNLL))
game.h文件:
#include<time.h>
#include<stdlib.h>
为了实现玩家下一个棋,然后电脑下一个棋的功能我们还需加上一个while循环。如下:
test.c文件:
while(1)
{
//玩家下棋
PlayerMove(board, ROW, COL);
DisplayBoard(board, ROW, COL);
//电脑下棋
ComputerMove(board, ROW, COL);
DisplayBoard(board, ROW, COL);
}
4. 判断游戏的输赢
思路:
此游戏无非只有三种结果:要么玩家赢,要么电脑赢,要么平局。所以我们可以写一个函数判断是这几种结果的哪一种,然后规定如果是玩家赢此函数返回“*”,如果是电脑赢则返回“#”,平局则返回“Q”,这几种都不是就说明游戏继续,那么就返回“C”.
要判断是否有赢的一方,无非就是判断是否出现了三个相同的棋子练成一条直线,而棋子连成的线无非就只有三种情况:竖线、横线、对角线。所以我们只需要判断是否出现了这三种情况的其中一种就可以了。而要判断是平局,则判断九宫格是否还有没有空格。
game.c文件:
int ItFull(char board[ROW][COL], int row, int col)
{
for (int i = 0; i < row; i++)
{
for (int j = 0;j < col; j++)
{
if (board[i][j] == ' ')
{
return 0;
}
}
}
return 1;
}
char ItWin(char board[ROW][COL], int row, int col)
{
//行
for (int i = 0; i < row; i++)
{
if (board[i][0] == board[i][1] && board[i][1] == board[i][2] && board[i][2] != ' ')
return board[i][1];
}
//列
for (int j = 0; j < col; j++)
{
if (board[0][j] == board[1][j] && board[1][j] == board[2][j] && board[2][j] != ' ')
return board[1][j];
}
//对角线
if (board[0][0] == board[1][1] && board[1][1] == board[2][2] && board[2][2] != 0)
{
return board[1][1];
}
if (ItFull(board, row, col))
{
return 'Q';
}
return 'C';
}
test.c文件:
//玩家下棋
PlayerMove(board, ROW, COL);
DisplayBoard(board, ROW, COL);
//判断输赢
char ret = ItWin(board, ROW, COL);
if (ret != 'C')
{
if (ret == '*')
{
printf("玩家赢了!!!\n");
}
break;
}
//电脑下棋
ComputerMove(board, ROW, COL);
DisplayBoard(board, ROW, COL);
//判断输赢
ItWin(board, ROW, COL);
if (ret != 'C')
{
if (ret == '#')
{
printf("电脑赢了!!!\n");
}
break;
}
完整代码:
game.h文件:
#include<stdio.h>
#include<stdlib.h>
#include<time.h>
#define ROW 3
#define COL 3
void InitBoard(char board[ROW][COL],int row,int col);
void DisplayBoard(char board[ROW][COL], int row, int col);
void PlayerMove(char board[ROW][COL], int row, int col);
void ComputerMove(char board[ROW][COL], int row, int col);
char ItWin(char board[ROW][COL], int row, int col);
test.c文件:
#include"game.h"
void menu()
{
printf("***************************\n");
printf("******** 1.play ********\n");
printf("******** 2.exit ********\n");
printf("***************************\n");
}
void game()
{
//第一步打印棋盘。
char board[ROW][COL] = { 0 };
//初始化棋盘
InitBoard(board, ROW, COL);
//打印棋盘
DisplayBoard(board, ROW, COL);
char ret;
while(1)
{
//玩家下棋
PlayerMove(board, ROW, COL);
DisplayBoard(board, ROW, COL);
//判断输赢
char ret = ItWin(board, ROW, COL);
if (ret != 'C')
{
if (ret == '*')
{
printf("玩家赢了!!!\n");
}
break;
}
//电脑下棋
ComputerMove(board, ROW, COL);
DisplayBoard(board, ROW, COL);
//判断输赢
ItWin(board, ROW, COL);
if (ret != 'C')
{
if (ret == '#')
{
printf("电脑赢了!!!\n");
}
break;
}
}
}
int main()
{
srand((unsigned int)time(NULL));
int input = 0;
do
{
menu();
printf("请选择>:");
scanf("%d", &input);
switch (input)
{
case 1:
game();
break;
case 0:
printf("退出游戏.\n");
break;
default:
printf("输入有误,请重新输入.\n");
}
} while (input);
return 0;
}
game.c文件:
#include"game.h"
void InitBoard(char board[ROW][COL], int row, int col)
{
for (int i = 0; i < row; i++)
{
for (int j = 0; j < col; j++)
{
board[i][j] = ' ';
}
}
}
void DisplayBoard(char board[ROW][COL], int row, int col)
{
for (int i = 0; i < row; i++)
{
for (int j = 0; j < col; j++)
{
printf(" %c ",board[i][j]);
if (j < col - 1)
printf("|");
}
printf("\n");
if (i < row - 1)
{
for (int j = 0; j < col; j++)
{
printf("---");
if (j < col - 1)
printf("|");
}
printf("\n");
}
}
}
void PlayerMove(char board[ROW][COL], int row, int col)
{
int x = 0, y = 0;
printf("玩家下棋>:\n");
while (1)
{
printf("请输入你要落子的坐标:");
scanf("%d%d", &x, &y);
if (x >= 1 && x <= row && y >= 1 && y <= col)
{
if (board[x - 1][y - 1] == ' ')
{
board[x - 1][y - 1] = '*';
break;
}
else
{
printf("输入的坐标已被占用,请重新输入\n");
}
}
else
{
printf("坐标非法,请重新输入\n");
}
}
}
void ComputerMove(char board[ROW][COL], int row, int col)
{
printf("电脑下棋:>\n");
while (1)
{
int x = rand() % row;
int y = rand() % row;
if (x <= row && x >= 1 && y <= row && y >= 1)
{
if (board[x][y] == ' ')
{
board[x][y] = '#';
break;
}
}
}
}
int ItFull(char board[ROW][COL], int row, int col)
{
for (int i = 0; i < row; i++)
{
for (int j = 0;j < col; j++)
{
if (board[i][j] == ' ')
{
return 0;
}
}
}
return 1;
}
char ItWin(char board[ROW][COL], int row, int col)
{
//行
for (int i = 0; i < row; i++)
{
if (board[i][0] == board[i][1] && board[i][1] == board[i][2] && board[i][2] != ' ')
return board[i][1];
}
//列
for (int j = 0; j < col; j++)
{
if (board[0][j] == board[1][j] && board[1][j] == board[2][j] && board[2][j] != ' ')
return board[1][j];
}
//对角线
if (board[0][0] == board[1][1] && board[1][1] == board[2][2] && board[2][2] != 0)
{
return board[1][1];
}
if (ItFull(board, row, col))
{
return 'Q';
}
return 'C';
}
运行图:
游戏优化:
让电脑生成一个数的方式来实现一个电脑下棋的效果,肯定是没有什么可玩性的,等后面学习算法之后,我们就加入一些算法将其变为一个棋艺高超的棋手了。