C语言实现三子棋游戏
- 代码下载
- 一、多文件思维
- 二、游戏总体思路与函数设计实现
-
- 2.1 游戏菜单Menu
- 2.2 显示棋盘ShowBoard
- 2.3 玩家移动PlayerMove
- 2.4 判断输赢Judge
- 2.5 电脑移动ComputerMove
- 2.5 游戏主控制函数Game
- 三、多文件代码清单
-
- 3.1 game.h
- 3.2 game.c
- 3.3 main.c
代码下载
Github源码下载地址:
https://github.com/Kyrie-leon/C_Project/tree/master/Three_Game
一、多文件思维
我们使用多文件实现三子棋游戏,培养多文件思维,分别为game.h、game.c和main.c
二、游戏总体思路与函数设计实现
三子棋游戏的主要思路为:
玩家通过菜单进入游戏->显示棋盘->玩家移动->判断输赢->电脑移动->判断输赢
上述函数封装在game.c文件中
2.1 游戏菜单Menu
void Menu()
{
printf("################################\n");
printf("#### 1.Play 2.Exit ####\n");
printf("################################\n");
printf("Please input your selection#: ");
}
2.2 显示棋盘ShowBoard
棋盘用一个二维数组来存储并显示,对于没有下过棋子的位置统一用’空格存储,由于电脑的分辨率不同,棋盘的形状需要不断调试。
void ShowBoard(char board[][COL],int row, int col)
{
printf(" | 1 | 2 | 3 |\n");
printf("----------------\n");
//外层循环控制每一行,内层循环控制每一列
for (int i = 0; i < ROW; i++)
{
printf(" %d | ",i+1);
for (int j = 0; j < COL; j++)
{
printf("%c | ", board[i][j]);
}
printf("\n----------------\n");
}
}
2.3 玩家移动PlayerMove
玩家棋子用X表示,在输入位置后需要判断落子的地方是否合法,主要为如下情况
1.越界,即超出棋盘范围,
2. 落子位置被占用,即该位置已经存在玩家棋子或者电脑棋子
void PlayerMove(char board[][COL], int row, int col)
{
//定义输入坐标x,y
int x = 0;
int y = 0;
while (1)
{
printf("请输入你的位置:");
scanf("%d %d", &x, &y);
if (x < 1 || x>3 || y < 1 || y>3)
{
printf("你输入的坐标有误!\n");
continue;
}
//需要注意用户输入的坐标从1开始,而程序定义的棋盘坐标从0开始
else if (board[x - 1][y - 1] != ' ')
{
printf("你输入的位置已经被占用!\n");
continue;
}
else
{
board[x - 1][y - 1] = P_COLOR;
break;
}
}
}
2.4 判断输赢Judge
判断输赢的几种情况已经在代码中给出注释,不懂的话可以评论问我
char Judge(char board[][COL], int row, int col)
{
//1.遍历每一行是否三子成珠
for (int i = 0; i < row; i++)
{
if (board[i][0] == board[i][1] && \
board[i][1] == board[i][2] && \
board[i][0] != ' ')
{
return board[i][0];
}
}
//2.遍历每一列是否三子成珠
for (int j = 0; j < col; j++)
{
if (board[0][j] == board[1][j] && \
board[1][j] == board[2][j] && \
board[0][j] != ' ')
{
return board[0][j];
}
}
//3.遍历九宫格对角线是否三子成珠
if (board[0][0] == board[1][1] && \
board[1][1] == board[2][2] && \
board[0][0] != ' ')
{
return board[0][0];
}
if (board[0][2] == board[1][1] && \
board[1][1] == board[2][0] && \
board[0][2] != ' ')
{
return board[0][2];
}
//4.没有出现三子成珠,且棋盘还有空位,继续下棋
for (int i = 0; i < row; i++)
{
for (int j = 0; j < col; j++)
{
if (board[i][j] == ' ')
{
return NEXT;
}
}
}
//5.上述条件都不满足,和棋
return DRAW;
}
2.5 电脑移动ComputerMove
电脑落子我们使用随机落子,如果想要更加智能可以采取一些策略
void ComputerMove(char board[][COL], int row, int col)
{
while (1)
{
int x = rand() % row;
int y = rand() % col;
if (board[x][y] == ' ')
{
board[x][y] = C_COLOR;
break;
}
}
}
2.5 游戏主控制函数Game
void Game()
{
//定义一个随机种子用于电脑落子
srand((unsigned long)time(NULL));
//定义棋盘
char board[ROW][COL];
//棋盘初始化为空
memset(board, ' ', sizeof(board));
//定义变量result用于判断输赢情况
char result='x';
do
{
ShowBoard(board, ROW, COL);
PlayerMove(board, ROW, COL);
result = Judge(board, ROW, COL);
//出现三子成珠,跳出循环,给出输赢结果
if (result != NEXT)
{
break;
}
ComputerMove(board, ROW, COL);
result = Judge(board, ROW, COL);
//出现三子成珠情况,跳出循环,给出输赢结果
if (result != NEXT)
{
break;
}
} while (1);
//打印输赢结果
if (P_COLOR == result)
{
printf("你赢了!\n");
}
else if (C_COLOR == result)
{
printf("你输了!\n");
}
else
{
printf("和棋!\n");
}
//此处再次调用显示棋盘函数,用于显示最终的落子情况,如果不调用该函数,会出现看不到最后一次落子的棋盘
ShowBoard(board, ROW, COL);
}
三、多文件代码清单
3.1 game.h
用于存放实现游戏的所有库函数和函数声明,以及一些宏定义方便后续更改
使用ifndef/define/endif防止头文件的重复包含和编译。
#ifndef _GAME_H
#define _GAME_H
#include <stdio.h>
#include <Windows.h>
#include <time.h>
#pragma warning(disable:4996)
//定义棋盘大小
#define ROW 3
#define COL 3
//定义玩家与电脑棋子颜色
#define P_COLOR 'X'
#define C_COLOR 'O'
#define NEXT 'N'
#define DRAW 'D'
void Menu();
void Game();
#endif
3.2 game.c
用于存放实现游戏的所有函数定义
#include "game.h"
void Menu()
{
printf("################################\n");
printf("#### 1.Play 2.Exit ####\n");
printf("################################\n");
printf("Please input your selection#: ");
}
void ShowBoard(char board[][COL],int row, int col)
{
printf(" | 1 | 2 | 3 |\n");
printf("----------------\n");
//外层循环控制每一行,内层循环控制每一列
for (int i = 0; i < ROW; i++)
{
printf(" %d | ",i+1);
for (int j = 0; j < COL; j++)
{
printf("%c | ", board[i][j]);
}
printf("\n----------------\n");
}
}
void PlayerMove(char board[][COL], int row, int col)
{
//定义输入坐标x,y
int x = 0;
int y = 0;
while (1)
{
printf("请输入你的位置:");
scanf("%d %d", &x, &y);
if (x < 1 || x>3 || y < 1 || y>3)
{
printf("你输入的坐标有误!\n");
continue;
}
//需要注意用户输入的坐标从1开始,而程序定义的棋盘坐标从0开始
else if (board[x - 1][y - 1] != ' ')
{
printf("你输入的位置已经被占用!\n");
continue;
}
else
{
board[x - 1][y - 1] = P_COLOR;
break;
}
}
}
char Judge(char board[][COL], int row, int col)
{
//1.遍历每一行是否三子成珠
for (int i = 0; i < row; i++)
{
if (board[i][0] == board[i][1] && \
board[i][1] == board[i][2] && \
board[i][0] != ' ')
{
return board[i][0];
}
}
//2.遍历每一列是否三子成珠
for (int j = 0; j < col; j++)
{
if (board[0][j] == board[1][j] && \
board[1][j] == board[2][j] && \
board[0][j] != ' ')
{
return board[0][j];
}
}
//3.遍历九宫格对角线是否三子成珠
if (board[0][0] == board[1][1] && \
board[1][1] == board[2][2] && \
board[0][0] != ' ')
{
return board[0][0];
}
if (board[0][2] == board[1][1] && \
board[1][1] == board[2][0] && \
board[0][2] != ' ')
{
return board[0][2];
}
//4.没有出现三子成珠,且棋盘还有空位,继续下棋
for (int i = 0; i < row; i++)
{
for (int j = 0; j < col; j++)
{
if (board[i][j] == ' ')
{
return NEXT;
}
}
}
//5.上述条件都不满足,和棋
return DRAW;
}
void ComputerMove(char board[][COL], int row, int col)
{
while (1)
{
int x = rand() % row;
int y = rand() % col;
if (board[x][y] == ' ')
{
board[x][y] = C_COLOR;
break;
}
}
}
void Game()
{
//定义一个随机种子用于电脑落子
srand((unsigned long)time(NULL));
//定义棋盘
char board[ROW][COL];
//棋盘初始化为空
memset(board, ' ', sizeof(board));
//定义变量result用于判断输赢情况
char result='x';
do
{
ShowBoard(board, ROW, COL);
PlayerMove(board, ROW, COL);
result = Judge(board, ROW, COL);
//出现三子成珠,跳出循环,给出输赢结果
if (result != NEXT)
{
break;
}
ComputerMove(board, ROW, COL);
result = Judge(board, ROW, COL);
//出现三子成珠情况,跳出循环,给出输赢结果
if (result != NEXT)
{
break;
}
} while (1);
//打印输赢结果
if (P_COLOR == result)
{
printf("你赢了!\n");
}
else if (C_COLOR == result)
{
printf("你输了!\n");
}
else
{
printf("和棋!\n");
}
//此处再次调用显示棋盘函数,用于显示最终的落子情况,如果不调用该函数,会出现看不到最后一次落子的棋盘
ShowBoard(board, ROW, COL);
}
3.3 main.c
实现三子棋游戏的主菜单和实现步骤
#include "game.h"
int main()
{
int select=0;
int quit = 0;
while(!quit)
{
Menu();
scanf("%d", &select);
switch(select)
{
case 1:
Game();
break;
case 2:
quit = 1;
break;
default:
printf("Please input again\n");
break;
}
}
printf("ByeBye!\n");
system("pause");
return 0;
}