任意阶三子棋的实现
C语言编写。
结构
test.c
测试游戏逻辑,main函数所在文件。
game.c
实现游戏代码
game.h
头文件声明
test.c
包含:
int main()
{
srand((unsigned int)time(NULL));//设置随机数的生成起点
int input = 0;
do
{
menu();
printf("Please Choose:>");
scanf("%d", &input);
switch (input)
{
case 1:
game();
break;
case 0:
printf("退出游戏\n");
break;
default:
printf("选择错误!\n");
break;
}
} while (input);
return 0;
}
目录选择包括进行游戏,退出游戏,重新选择。
menu是简单的打印:
void menu()
{
printf("******************************\n");
printf("**********1. Play*************\n");
printf("**********0. Exit*************\n");
printf("******************************\n");
}
game是进行游戏的主要函数:
void game()
{
char ret = 0;
char board[ROW][COL] = {0};
//初始化棋盘
InitBoard(board,ROW,COL);
DisplayBoard(board,ROW,COL);
//下棋
while (1)
{
PlayerMove(board,ROW,COL);
//判断输赢
ret = Iswin(board, ROW, COL);
if (ret != 'C')
{
break;
}
DisplayBoard(board, ROW, COL);
ComputerMove(board, ROW, COL);
ret = Iswin(board, ROW, COL);
if (ret != 'C')
{
break;
}
DisplayBoard(board, ROW, COL);
}
if (ret == '*')
{
printf("Player Wins!\n");
}
else if (ret == '#')
{
printf("Computer Wins!\n");
}
else
{
printf("Tie!\n");
}
DisplayBoard(board, ROW, COL);
}
game按照如下顺序完成功能:
- 初始化棋盘;
- 显示棋盘;
- 玩家下棋+判断输赢;
- 电脑下棋+判断输赢。
以上功能均在game.c中实现。
game.c
初始化棋盘:
void InitBoard(char board[ROW][COL], int row, int col)
{
int i = 0;
int j = 0;
for (i = 0; i < row; i++)
{
for (j = 0; j < col; j++)
{
board[i][j] = ' ';
}
}
}
本质是将棋盘处理为一个二维数组,下棋是在填充这个二维数组。初始化时,棋盘是空的,因此数组被初始化为全空格。
显示棋盘:
void DisplayBoard(char board[ROW][COL], int row, int col)
{
int i = 0;
for (i = 0; i < row; i++)
{
int j = 0;
for (j = 0; j < col; j++)
{
printf(" %c ", board[i][j]);
if (j < col - 1)
printf("|");
}
printf("\n");
//打印分割行
if (i < row - 1)
{
int j = 0;
for (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;
int y = 0;
while (1)
{
printf("Please enter pos:>");
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("Occupied!");
}
}
else
{
printf("Wrong Input!\n");
}
}
}
玩家棋子标记为* 。
电脑下棋:
void ComputerMove(char board[ROW][COL], int row, int col)
{
printf("Computer Move:>\n");
int x = 0;
int y = 0;
while (1)
{
x = rand() % row;//0~2
y = rand() % col;//0~2
if (board[x][y] == ' ')
{
board[x][y] = '#';
break;
}
}
}
电脑按照随机填空的方式下棋,main函数中的srand用来生成随机种子。
判断棋盘是否占满:
//满了返回1 不满返回0
int IsFull(char board[ROW][COL], int row, int col)
{
int i = 0;
int j = 0;
for (i = 0; i < row; i++)
{
for (j = 0; j < col; j++)
{
if (board[i][j] == ' ')
{
return 0;
}
}
}
return 1;
}
主要用于判断输赢使用。输赢共有玩家赢、电脑赢、平局、继续4种。
判断输赢:
char Iswin(char board[ROW][COL], int row, int col)
{
//判断行
int i = 0;
int j = 0;
int k = 0;
for (i = 0; i < row; i++)
{
for (j = 0; j < col-2; j++)
{
if (board[i][j] == board[i][j + 1] && board[i][j + 1] == board[i][j + 2] && board[i][j + 1] != ' ')
{
return board[i][j + 1];
}
}
}
//判断列
for (j = 0; j < col; j++)
{
for (i = 0; i < row - 2; i++)
{
if (board[i][j] == board[i+1][j] && board[i+1][j] == board[i+2][j] && board[i+1][j] != ' ')
{
return board[i+1][j];
}
}
}
//判断对角线
int ret = col - 3;//判断除了主对角线之外还有多少对角线需要做判断
//主对角线
for (i = 0; i < row - 2; i++)
{
if (board[i][i] == board[i + 1][i + 1] && board[i + 1][i + 1] == board[i + 2][i + 2] && board[i + 1][i + 1] != ' ')
{
return board[i + 1][i + 1];
}
}
//主方向
for (k = 1; k <= ret; k++)
{
for (i = 0; i <= row -k -2 ; i++)
{
for (j = 0; j < col-2 ; j++)
{
if (board[i][j] == board[i + 1][j + 1] && board[i + 1][j + 1] == board[i + 2][j + 2] && board[i + 1][j + 1] != ' ')
{
return board[i + 1][j + 1];
}
}
}
}
//副对角线
for (i = 0; i < row - 2; i++)
{
for (j = col; j >= 2; j--)
{
if (board[i][j] == board[i+1][j-1] && board[i+1][j-1] == board[i+2][j-2] && board[i+1][j-1] != ' ')
{
return board[i+1][j-1];
}
}
}
//副方向
for (k = 1; k <= ret; k++)
{
for (i = 0; i <= row - k - 2; i++)
{
for (j = col - 2; j >= 0; j--)
{
if (board[i][j] == board[i + 1][j - 1] && board[i + 1][j - 1] == board[i + 2][j - 2] && board[i + 1][j - 1] != ' ')
{
return board[i + 1][j - 1];
}
}
}
}
//没有人赢,判断平局
if (IsFull(board, row, col))
{
return 'Q';
}
//游戏继续
return 'C';
}
判断结果如下:
返回 * : 玩家赢
返回# : 电脑赢
返回Q:平局
返回C:继续
由于是任意阶的三子棋,判断逻辑较3*3棋盘复杂一些。
game.h
头文件,声明。
棋盘阶数通过ROW、COL的值来修改。
#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
#include <time.h>
#include <stdlib.h>
#define ROW 5
#define COL 5
//初始化棋盘
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);
//判断输赢
//玩家赢 - ‘*’
//电脑赢 - ‘#’
//平局 -‘Q’
//继续 - ‘C’
//
char Iswin(char board[ROW][COL], int row, int col);
运行效果
如果ROW≠COL,会有BUG,等待后续改进。
说明
最近在看比特鹏哥的C语言视频,到数组这里。任意阶的三子棋我目前没有找到代码示例,这里只是一个学习的进度记录,有疏漏还请轻喷。