众所周知,三子棋是一个经典的小游戏,那么如何通过C语言来实现三子棋呢?本篇博客将系统的教大家如何从零开始实现一款三子棋小游戏,思路才是重中之重。
三子棋
预期的效果:采用模块化编程,打印一个棋盘,玩家通过坐标来选择下棋位置。
一共分为几个步骤:
1:游戏菜单,选择进行游戏或者退出游戏。
2:输出一个空的棋盘(3*3)。
3:玩家选择坐标下棋。
4:电脑随机空位置下棋。
5:判断输赢。
6:重新开始。
打印菜单
输出一个简单的游戏菜单,通过输入1或者0来选择开始游戏或者退出游戏,输入非1和0的数字提示输入错误,请重新输入,游戏可以多次进行。
以下为代码:
void menu()
{
printf("************************\n");
printf("******* 1. play ********\n");
printf("******* 0. quit ********\n");
printf("************************\n");
}
void test()
{
int n = 0;
do
{
menu();
printf("请选择\n");
scanf("%d", &n);
switch (n)
{
case 1:
//game();
break;
case 0:
break;
default:
printf("输入错误,请重新输入\n");
break;
}
} while (n);
}
int main()
{
test();
return 0;
}
此处game函数是游戏的实现过程,先不作声明。
棋盘打印和初始化
这里的预期是:打印一个3*3的井字棋棋盘

那么该如何实现呢?
1:创建一个3行3列的二维数组来存放下棋的数据。
2:在打印前将棋盘初始化,使其有我们预期的样子。
3:打印棋盘
此时我们需要创建一个新的源文件game.c和一个头文件game.h,来保存函数的实现过程,使主函数更易懂。
以下为代码:
void game()
{
//存放下棋数据
char board[ROW][COL] = { 0 };
//初始化棋盘为全空格
init_board(board, ROW, COL);
//打印棋盘
print_board(board, ROW, COL);
}
void init_board(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++)
{
board[i][j] = ' ';
}
}
}
void print_board(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)
{
for (j = 0; j < col; j++)
{
printf("---");
if (j < col - 1)
{
printf("|");
}
}
printf("\n");
}
}
}
玩家下棋&电脑下棋
玩家下棋其实就是通过二维数组选择一个空的位置来下棋,当选择的位置有棋子的时候提示“该位置已被占用,请重新输入”,当坐标输入错误的时候提示“坐标非法,请重新输入”。
电脑下棋通过随机值来模拟,当该位置有棋子时,重新随机一个位置。(由于技术有限,无法做到电脑AI智能输入,此处仅用来模拟思路)
以下为代码
//玩家下棋
void player_move(char board[ROW][COL], int row, int col)
{
int x = 0;
int y = 0;
printf("请玩家下棋:");
scanf("%d %d", &x, &y);
while (1)
{
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 computer_move(char board[ROW][COL], int row, int col)
{
int x = 0;
int y = 0;
printf("电脑下棋:\n");
while (1)
{
x = rand() % row;
y = rand() % col;//得0~2之间的值
if (board[x][y] == ' ')
{
board[x][y] = '#';
break;
}
}
}
判断输赢
玩家和电脑每下一步棋就应该判断一次是否有人获胜,如果玩家获胜返回*,电脑获胜返回#,或是否平局,写一个函数判断棋盘是否为满,如果棋盘已满且无人获胜,返回Q,什么都没有发生则游戏继续,返回C。
以下为代码:
//判断棋盘是否满了
int full(char borad[ROW][COL], int row, int col)
{
int i = 0;
for (i = 0; i < row; i++)
{
int j = 0;
for (j = 0; j < col; j++)
{
if (borad[i][j] == ' ')
{
return 0;//没满
}
}
}
return 1;//满了
}
//判断输赢
char who_win(char board[ROW][COL], int row, int col)
{
int i = 0;
//判断行
for (i = 0; i < row; i++)
{
if (board[i][0] == board[i][1] && board[i][1] == board[i][2] && board[i][1] != ' ')
{
return board[i][1];
}
}
//判断列
for (i = 0; i < col; i++)
{
if (board[0][i] == board[1][i] && board[1][i] == board[2][i] && board[1][i] != ' ')
{
return board[1][i];
}
}
//判断对角线
if (board[0][0] == board[1][1] && board[1][1] == board[2][2] && board[1][1] != ' ')
{
return board[1][1];
}
if (board[2][0] == board[1][1] && board[1][1] == board[0][2] && board[1][1] != ' ')
{
return board[1][1];
}
//判断平局
if (full(board, row, col) == 1)
{
return 'Q';
}
return 'C';
}
game函数
此时主要代码已经完成,应该调整game函数,使其更合理。
调整如下:
void game()
{
char w = 0;
//存放下棋数据
char board[ROW][COL] = { 0 };
//初始化棋盘为全空格
init_board(board, ROW, COL);
//打印棋盘
print_board(board, ROW, COL);
while (1)
{
//玩家下棋
player_move(board, ROW, COL);
print_board(board, ROW, COL);
w = who_win(board, ROW, COL);
if (w != 'C')
{
break;
}
//电脑下棋
computer_move(board, ROW, COL);
print_board(board, ROW, COL);
w = who_win(board, ROW, COL);
if (w != 'C')
{
break;
}
}
if (w == '*')
{
printf("玩家赢了\n");
}
else if (w == '#')
{
printf("电脑赢了\n");
}
else
{
printf("平局\n");
}
print_board(board, ROW, COL);
}
整体代码
三子棋游戏基本功能到现在已经部分实现。
以下是整体代码:
//game.h
#pragma once
#include <stdio.h>
#include <time.h>
#include <stdlib.h>
#define ROW 3
#define COL 3
//初始化棋盘
void init_board(char board[ROW][COL], int row, int col);
//打印棋盘
void print_board(char board[ROW][COL], int row, int col);
//玩家下棋
void player_move(char board[ROW][COL], int row, int col);
//电脑下棋
void computer_move(char board[ROW][COL], int row, int col);
//判断输赢
char who_win(char board[ROW][COL], int row, int col);
//game.c
#define _CRT_SECURE_NO_WARNINGS 1
#include "game.h"
void init_board(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++)
{
board[i][j] = ' ';
}
}
}
void print_board(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)
{
for (j = 0; j < col; j++)
{
printf("---");
if (j < col - 1)
{
printf("|");
}
}
printf("\n");
}
}
}
void player_move(char board[ROW][COL], int row, int col)
{
int x = 0;
int y = 0;
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 computer_move(char board[ROW][COL], int row, int col)
{
int x = 0;
int y = 0;
printf("电脑下棋:\n");
while (1)
{
x = rand() % row;
y = rand() % col;//得0~2之间的值
if (board[x][y] == ' ')
{
board[x][y] = '#';
break;
}
}
}
static int full(char borad[ROW][COL], int row, int col)
{
int i = 0;
for (i = 0; i < row; i++)
{
int j = 0;
for (j = 0; j < col; j++)
{
if (borad[i][j] == ' ')
{
return 0;//没满
}
}
}
return 1;//满了
}
char who_win(char board[ROW][COL], int row, int col)
{
int i = 0;
//判断行
for (i = 0; i < row; i++)
{
if (board[i][0] == board[i][1] && board[i][1] == board[i][2] && board[i][1] != ' ')
{
return board[i][1];
}
}
//判断列
for (i = 0; i < col; i++)
{
if (board[0][i] == board[1][i] && board[1][i] == board[2][i] && board[1][i] != ' ')
{
return board[1][i];
}
}
//判断对角线
if (board[0][0] == board[1][1] && board[1][1] == board[2][2] && board[1][1] != ' ')
{
return board[1][1];
}
if (board[2][0] == board[1][1] && board[1][1] == board[0][2] && board[1][1] != ' ')
{
return board[1][1];
}
//判断平局
if (full(board, row, col) == 1)
{
return 'Q';
}
return 'C';
}
//test.c
#define _CRT_SECURE_NO_WARNINGS 1
#include "game.h"
//测试三子棋游戏的逻辑
void game()
{
char w = 0;
//存放下棋数据
char board[ROW][COL] = { 0 };
//初始化棋盘为全空格
init_board(board, ROW, COL);
//打印棋盘
print_board(board, ROW, COL);
while (1)
{
//玩家下棋
player_move(board, ROW, COL);
print_board(board, ROW, COL);
w = who_win(board, ROW, COL);
if (w != 'C')
{
break;
}
//电脑下棋
computer_move(board, ROW, COL);
print_board(board, ROW, COL);
w = who_win(board, ROW, COL);
if (w != 'C')
{
break;
}
}
if (w == '*')
{
printf("玩家赢了\n");
}
else if (w == '#')
{
printf("电脑赢了\n");
}
else
{
printf("平局\n");
}
print_board(board, ROW, COL);
}
void menu()
{
printf("************************\n");
printf("******* 1. play ********\n");
printf("******* 0. quit ********\n");
printf("************************\n");
}
void test()
{
int n = 0;
srand((unsigned int)time(NULL));//获取随机值
do
{
menu();
printf("请选择\n");
scanf("%d", &n);
switch (n)
{
case 1:
game();
break;
case 0:
break;
default:
printf("输入错误,请重新输入\n");
break;
}
} while (n);
}
int main()
{
test();
return 0;
}
总结
数组实现三子棋作为一道经典的C语言题目,对初学者来说是比较困难的,本篇博客的意义是给和我一样是初学者的朋友一丝灵感,一点思路,也为了让自己理顺思路,加深理解,方便日后复盘。
真心希望大家能从这篇博客学到点东西,如果文章中有思路不清晰的地方或者写的不对的地方请谅解,欢迎各位大佬指点。