目 录
一、三子棋游戏介绍
大多数人应该都玩过三子棋游戏,随便拿张纸,在上边横竖各画两条线形成一个九宫格,即使一个简单的棋盘,横着数、竖着数、沿着正反对角线数,谁率先用自己的三个棋子在这些方向上连成一条线,谁就是赢家。接下来文中就将用C语言实现三子棋游戏
二、游戏功能函数分析
1 菜单显示函数
虽然只是一个简单的小游戏,但有个菜单界面还是必要的,这个界面一般用printf()函数调整输出自己喜欢的样式就可以了。以下是函数具体的代码实现:
//显示游戏菜单功能
void Menu() {
printf("\n 三 子 棋 \n\n\n");
printf(" 菜 单 \n\n");
printf("************ 1 游戏开始 ************\n");
printf("************ 0 退出游戏 ************\n");
}
2 菜单选择函数
既然有了菜单,那就针对菜单做一个进行选择的功能吧,可以看见菜单里目前就是1\0两种选择,那么在这个函数里我们要实现的主要两个点是:提醒玩家进行选择并进行返回;在返回玩家的选择之前确认其输入是1\0两个值之间的一个,如果不是,提醒玩家重新输入选择。以下是函数具体的代码实现:
//选择功能
int MenuSelect() {
int select = 0;
while (1) {
printf("请选择(1\\0):>");
scanf("%d", &select);
getchar(); //清理换行符'\n'
if ((select == 1) || (select == 0)) {
return select;
}
else {
printf("选择无效,请重新选择!\n");
}
}
}
3 选择确认函数
当玩家选择退出游戏时,这里为了避免玩家不小心选择错误的可能,设置了进行选择确认的函数,确认玩家是否真的要退出游戏,如果是选择Y,否选择N(不区分大小写)并返回选择值。以下是函数具体的代码实现:
//选择确认功能
char SelectConfirm() {
char select = 'Y';
while (1) {
printf("请确认是否退出游戏(Y\\N):>");
scanf("%c", &select);
getchar(); //清理换行符'\n'
if ((select >= 'a') && (select <= 'z')) {
select = 'A' + (select - 'a');
}
if ((select == 'Y') || (select == 'N')) {
return select;
}
else {
printf("选择无效,请重新选择!\n");
}
}
}
4 显示当前棋盘状态函数
下棋首先得有棋盘,三子棋的棋盘是一个九宫格的形状,具体想用什么符号搭建出这样一个棋盘看自己的喜好。即是棋盘,自然也要显示出棋盘上的棋子,每次落子后,都显示出当前棋盘,可以及时观察到游戏进行状态。以下是函数具体的代码实现:
//显示当前棋盘状态功能
void ChessBoard() {
int i = 0;
int j = 0;
printf("\n当前棋盘:\n");
for (i = 0; i < ROW; i++) {
printf("\t ");
for (j = 0; j < COL; j++) {
printf(" %c ", board[i][j]);
if (j < COL - 1) {
printf("|");
}
}
printf("\n");
if (i < ROW - 1) {
printf("\t ");
for (j = 0; j < COL; j++) {
printf("---");
if (j < COL - 1) {
printf("|");
}
}
}
printf("\n");
}
}
5 棋盘初始化函数
下棋前还需要确保棋盘上是空的,这里以二维数组来表示棋盘上对应位置的棋子,用空格通过循环对棋盘进行初始化。以下是函数具体的代码实现:
//棋盘初始化功能
void ChessBoard_Initial() {
int i = 0;
int j = 0;
for (i = 0; i < 3; i++) {
for (j = 0; j < 3; j++) {
board[i][j] = ' ';
}
}
}
6 玩家下棋函数
有了棋盘就可以开始下棋了,下棋首先要确定所执的棋子以及落子的位置,这里设置函数的参数为代表棋子的符号以确定下棋方,落子前要确认落子的位置是否合理,如果玩家选择的落子位置超出了棋盘范围或者该位置上已有棋子,则有必要提醒玩家重新选择位置。以下是函数具体的代码实现:
//下棋功能
void PlayChess(char chess) {
int row = 1;
int col = 1;
while (1) {
printf("玩家:请输入下棋位置(行 列):>");
scanf("%d %d", &row, &col);
getchar(); //清理换行符'\n'
if (((row >= 1) && (row <= ROW)) && ((col >= 1) && (col <= ROW))) {
if (board[row - 1][col - 1] == ' ') {
board[row - 1][col - 1] = chess;
break;
}
else {
printf("\n此处已有棋子,请重新下棋!\n");
}
}
else {
printf("\n输入不合法,请重新输入!\n");
}
}
}
7 电脑下棋函数
下棋是对弈游戏,需要两个游戏玩家,如果只有一个人时,则可以与电脑进行游戏,这里通过时间戳产生随机数,通过随机数来随机生成电脑方的在棋盘范围内的落子位置。同样,落子前要确认落子的位置是否合理,如果电脑随机生成的落子位置上已有棋子,则通过循环重新选择位置。以下是函数具体的代码实现:
//电脑下棋功能
void ComputerPlay(char chess) {
srand((unsigned int)time(NULL));
int row = 0;
int col = 0;
while (1) {
row = rand() % 3;
col = rand() % 3;
if (board[row][col] == ' ') {
board[row][col] = chess;
break;
}
}
printf("电脑:下棋位置(行 列):>%d %d\n", row, col);
}
8 棋局状态判断函数
在下棋的过程中需要随时判断棋局状态以确定接下来是否还要继续进行当局游戏,根据三子棋游戏输赢的判定规则,依此访问横、竖、对角线上的落子情况:若有一方棋子可连成一线,则返回赢方棋子符号,标志游戏结束;若无胜方,且棋盘上仍有空位,则返回空格表示游戏继续;若无胜方,且棋盘已满,则返回'\0'符号表示游戏结束,双方平局。以下是函数具体的代码实现:
//判断当前棋局,确认是否结束游戏,并返回获胜棋子
char Judge(char chess1, char chess2) {
int count1 = 0; //棋子1计数
int count2 = 0; //棋子2计数
int count3 = 0; //空格计数
int i = 0;
int j = 0;
//行判断
for (i = 0; i < ROW; i++) {
count1 = 0;
count2 = 0;
for (j = 0; j < COL; j++) {
if (board[i][j] == chess1) {
count1++;
}
else if (board[i][j] == chess2) {
count2++;
}
else {
count3++;
}
}
if (count1 == 3) {
return chess1;
}
else if (count2 == 3) {
return chess2;
}
}
if (count3 == 0) {
return '\0'; //表示棋盘已满,游戏结束
}
//列判断
for (j = 0; j < COL; j++) {
count1 = 0;
count2 = 0;
for (i = 0; i < ROW; i++) {
if (board[i][j] == chess1) {
count1++;
}
else if (board[i][j] == chess2) {
count2++;
}
}
if (count1 == 3) {
return chess1;
}
else if (count2 == 3) {
return chess2;
}
}
//正对角判断
count1 = 0;
count2 = 0;
for (i = 0, j = 0; (i < ROW) && (j < COL); i++, j++) {
if (board[i][j] == chess1) {
count1++;
}
else if (board[i][j] == chess2) {
count2++;
}
}
if (count1 == 3) {
return chess1;
}
else if (count2 == 3) {
return chess2;
}
//反对角判断
count1 = 0;
count2 = 0;
for (i = 0, j = COL - 1; (i < ROW) && (j >= 0); i++, j--) {
if (board[i][j] == chess1) {
count1++;
}
else if (board[i][j] == chess2) {
count2++;
}
}
if (count1 == 3) {
return chess1;
}
else if (count2 == 3) {
return chess2;
}
return ' '; //表示游戏继续
}
三、游戏功能函数的整合
将上述函数整合进game.c文件中,并在相应的game.h头文件中对各个函数进行声明,同时在game.c文件中包含头文件game.h。具体实现如下:
#define _CRT_SECURE_NO_WARNINGS 1
#include "game.h"
//以二维数组表示棋盘
char board[ROW][COL] = {0};
//显示游戏菜单功能
void Menu() {
printf("\n 三 子 棋 \n\n\n");
printf(" 菜 单 \n\n");
printf("************ 1 游戏开始 ************\n");
printf("************ 0 退出游戏 ************\n");
}
//选择功能
int MenuSelect() {
int select = 0;
while (1) {
printf("请选择(1\\0):>");
scanf("%d", &select);
getchar(); //清理换行符'\n'
if ((select == 1) || (select == 0)) {
return select;
}
else {
printf("选择无效,请重新选择!\n");
}
}
}
//选择确认功能
char SelectConfirm() {
char select = 'Y';
while (1) {
printf("请确认是否退出游戏(Y\\N):>");
scanf("%c", &select);
getchar(); //清理换行符'\n'
if ((select >= 'a') && (select <= 'z')) {
select = 'A' + (select - 'a');
}
if ((select == 'Y') || (select == 'N')) {
return select;
}
else {
printf("选择无效,请重新选择!\n");
}
}
}
//棋盘初始化功能
void ChessBoard_Initial() {
int i = 0;
int j = 0;
for (i = 0; i < 3; i++) {
for (j = 0; j < 3; j++) {
board[i][j] = ' ';
}
}
}
//显示当前棋盘状态功能
void ChessBoard() {
int i = 0;
int j = 0;
printf("\n当前棋盘:\n");
for (i = 0; i < ROW; i++) {
printf("\t ");
for (j = 0; j < COL; j++) {
printf(" %c ", board[i][j]);
if (j < COL - 1) {
printf("|");
}
}
printf("\n");
if (i < ROW - 1) {
printf("\t ");
for (j = 0; j < COL; j++) {
printf("---");
if (j < COL - 1) {
printf("|");
}
}
}
printf("\n");
}
}
//下棋功能
void PlayChess(char chess) {
int row = 1;
int col = 1;
while (1) {
printf("玩家:请输入下棋位置(行 列):>");
scanf("%d %d", &row, &col);
getchar(); //清理换行符'\n'
if (((row >= 1) && (row <= ROW)) && ((col >= 1) && (col <= ROW))) {
if (board[row - 1][col - 1] == ' ') {
board[row - 1][col - 1] = chess;
break;
}
else {
printf("\n此处已有棋子,请重新下棋!\n");
}
}
else {
printf("\n输入不合法,请重新输入!\n");
}
}
}
//电脑下棋功能
void ComputerPlay(char chess) {
srand((unsigned int)time(NULL));
int row = 0;
int col = 0;
while (1) {
row = rand() % 3;
col = rand() % 3;
if (board[row][col] == ' ') {
board[row][col] = chess;
break;
}
}
printf("电脑:下棋位置(行 列):>%d %d\n", row, col);
}
//判断当前棋局,确认是否结束游戏,并返回获胜棋子
char Judge(char chess1, char chess2) {
int count1 = 0; //棋子1计数
int count2 = 0; //棋子2计数
int count3 = 0; //空格计数
int i = 0;
int j = 0;
//行判断
for (i = 0; i < ROW; i++) {
count1 = 0;
count2 = 0;
for (j = 0; j < COL; j++) {
if (board[i][j] == chess1) {
count1++;
}
else if (board[i][j] == chess2) {
count2++;
}
else {
count3++;
}
}
if (count1 == 3) {
return chess1;
}
else if (count2 == 3) {
return chess2;
}
}
if (count3 == 0) {
return '\0'; //表示棋盘已满,游戏结束
}
//列判断
for (j = 0; j < COL; j++) {
count1 = 0;
count2 = 0;
for (i = 0; i < ROW; i++) {
if (board[i][j] == chess1) {
count1++;
}
else if (board[i][j] == chess2) {
count2++;
}
}
if (count1 == 3) {
return chess1;
}
else if (count2 == 3) {
return chess2;
}
}
//正对角判断
count1 = 0;
count2 = 0;
for (i = 0, j = 0; (i < ROW) && (j < COL); i++, j++) {
if (board[i][j] == chess1) {
count1++;
}
else if (board[i][j] == chess2) {
count2++;
}
}
if (count1 == 3) {
return chess1;
}
else if (count2 == 3) {
return chess2;
}
//反对角判断
count1 = 0;
count2 = 0;
for (i = 0, j = COL - 1; (i < ROW) && (j >= 0); i++, j--) {
if (board[i][j] == chess1) {
count1++;
}
else if (board[i][j] == chess2) {
count2++;
}
}
if (count1 == 3) {
return chess1;
}
else if (count2 == 3) {
return chess2;
}
return ' '; //表示游戏继续
}
#define _CRT_SECURE_NO_WARNINGS 1
#include <stdio.h>
#include <stdlib.h>
#include <Windows.h>
#include <time.h>
#define ROW 3
#define COL 3
//显示游戏菜单功能
void Menu();
//选择功能
int MenuSelect();
//选择确认功能
char SelectConfirm();
//棋盘初始化功能
void ChessBoard_Initial();
//显示当前棋盘状态功能
void ChessBoard();
//下棋功能
void PlayChess();
//电脑下棋功能
void ComputerPlay();
//判断当前棋局,确认是否结束游戏
char Judge();
四、三子棋游戏的实现
编辑源文件test01.c,根据三子棋游戏的流程:1.菜单显示;2.玩家选择进入游戏后进行模式选择(玩家VS玩家(1) or 玩家VS电脑(0));3.模式选择完成后,由玩家选择自己想使用的棋子符号;4.完成上述选择后,开始游戏,先进行棋盘的初始化,显示出当前棋盘。如果选择模式1,由玩家双方交替下棋(虽然是两个玩家,但仍是在同一台电脑上操作),如果选择模式0,由玩家和电脑交替下棋,并在每次落子后进行棋局判断;5.一局游戏结束由玩家进行选择是否需要返回主菜单界面,若是则返回并进入下次循环中,若否则退出游戏。在游戏的过程中,为界面显示更加干净简洁,使用system("cls")函数进行界面清理,使用Sleep()延时函数设置合适的延时时长显示电脑落子选择后进行界面清理。以下是具体的代码实现:
#define _CRT_SECURE_NO_WARNINGS 1
#include "game.h"
//游戏测试
int main() {
int select = 0;
char selectConfirm = 'Y';
char gameConfirm = ' '; //确认游戏状态
char chess1 = 0;
char chess2 = 0;
while (1) {
Menu();
select = MenuSelect();
if (select == 1) {
system("cls");
printf("游戏模式(玩家VS玩家(1) or 玩家VS电脑(0)),");
select = MenuSelect();
printf("请选择玩家1棋子符号:>");
scanf("%c", &chess1);
getchar();
printf("请选择玩家2(电脑)棋子符号:>");
scanf("%c", &chess2);
getchar();
system("cls");
printf("\n游戏开始!\n");
ChessBoard_Initial();
ChessBoard();
while (1) {
PlayChess(chess1);
system("cls");
ChessBoard();
gameConfirm = Judge(chess1, chess2);
if (gameConfirm == ' ') {
;
}
else if (gameConfirm == '\0') {
printf("游戏结束,双方平局!\n");
break;
}
else {
printf("游戏结束,执%c棋方获胜!\n", gameConfirm);
break;
}
if (select == 1) {
PlayChess(chess2);
system("cls");
ChessBoard();
}
else {
ComputerPlay(chess2);
Sleep(800);
system("cls");
ChessBoard();
}
gameConfirm = Judge(chess1, chess2);
if (gameConfirm == ' ') {
continue;
}
else if (gameConfirm == '\0') {
printf("游戏结束,双方平局!\n");
break;
}
else {
printf("游戏结束,执%c棋方获胜!\n", gameConfirm);
break;
}
}
printf("返回菜单或直接退出游戏,");
select = MenuSelect();
if (select == 0) {
selectConfirm = SelectConfirm();
if (selectConfirm == 'Y') {
printf("退出游戏!\n");
break;
}
}
}
else {
selectConfirm = SelectConfirm();
if (selectConfirm == 'Y') {
printf("退出游戏!\n");
break;
}
}
system("cls");
}
return 0;
}
五、游戏过程截图
以下为游戏过程部分截图: