C語言實(shí)現(xiàn)簡易五子棋小游戲
本文實(shí)例為大家分享了C語言實(shí)現(xiàn)簡單五子棋小游戲的具體代碼,供大家參考,具體內(nèi)容如下
效果圖如下:

設(shè)計(jì)思路:
棋盤設(shè)計(jì)為15×15格,初始狀態(tài)光標(biāo)在棋盤的中央,白棋先走,輪流落子,當(dāng)一方連成五子或下滿棋盤時(shí),游戲結(jié)束(連成五子的一方獲勝,下滿棋盤為和棋)。當(dāng)游戲一方勝利后顯示勝利信息,提示信息利用漢字點(diǎn)陣輸出。
程序游戲是一個(gè)二維平面圖,可用二維數(shù)組來實(shí)現(xiàn),數(shù)組兩個(gè)下標(biāo)可以表示棋盤上的位置,數(shù)組元素的值代表棋格上的狀態(tài),共有三種情況,分別是0代表空格,1代表白棋,2代表黑棋。程序的主要工作是接收棋手按鍵操作,棋手1用設(shè)定四個(gè)鍵控制光標(biāo)移動(dòng),回車鍵表示落子。棋手2用另四個(gè)鍵控制光標(biāo)移動(dòng),空格鍵表示落子。接收到回車鍵或空格鍵,說明棋手落子,先判斷是否是有效位置,即有棋子的位置不能重疊落子。落子成功后,馬上判斷以該位置為中心的八個(gè)方向:上、下、左、右、左上、左下、右上、右下是否有相同顏色的棋子連成五子,如果連成五子,則游戲結(jié)束。
#include<stdio.h>
#include<stdlib.h>
#include<windows.h>
#pragma comment(lib, "WINMM.LIB")
#include <mmsystem.h>
#include<conio.h>
#include<time.h>
#define width 32 //棋盤總寬度
#define high 31 //棋盤總高度
#define MAX_X 15 //棋盤橫向格子數(shù)
#define MAX_Y 15 //棋盤縱向格子數(shù)
#define WIDTH (16+width) //游戲總高度
#define HIGH (high+4) //游戲總高度
#define player1 1 //白子玩家
#define player2 2 //黑子玩家
#define emptyPlayer 0//無子
#define Unplayer -2 //中途退出游戲,無玩家獲勝
typedef struct Stack{
//記錄下每次落子的坐標(biāo)
int x[MAX_X*MAX_Y];
int y[MAX_X*MAX_Y];
//相當(dāng)于棧頂指針
int top;
}Stack;
int pos[MAX_X][MAX_Y];//存儲(chǔ)棋盤上各位置處的狀態(tài) 比如有白子為1, 有黑子為2,無子為0
int px,py; //光標(biāo)位置
int player = 1;//記錄當(dāng)前玩家 默認(rèn)玩家從白方開始
int flag1 = 0;//標(biāo)志游戲開始
int gameOver_player = -1;//判斷結(jié)束的標(biāo)志
int pre_px = -1, pre_py = -1;//記錄下上一次的坐標(biāo)位置
void gotoxy(int x,int y);//設(shè)置CMD窗口光標(biāo)位置
void hide_cursor(); //隱藏CMD窗口光標(biāo)
void map();//打印地圖
void game_Description();//打印動(dòng)態(tài)游戲說明
void initMapState();//初始化游戲位置數(shù)據(jù)
void mapState(int qizi);//數(shù)組記錄下對應(yīng)位置的狀態(tài)
int isGoPlay();//判斷是否可以落子
int hasGoPlay(int Player);//以落子處為中心,判斷已經(jīng)落子后的棋盤是否五子相連
void goPlay(int Player, Stack* p);//落子 Player 1 2 0
void yiDongKuang();//移動(dòng)框
void player1_move();//玩家1_移動(dòng)
void player2_move();//玩家2_移動(dòng)
int gameOver();//判斷游戲是否結(jié)束
Stack* createStack();//創(chuàng)建空棧
void push(Stack* p, int x, int y);//入棧
void color(const unsigned short textColor);//自定義函根據(jù)參數(shù)改變顏色
//void setColor(unsigned short backColor);//設(shè)置游戲背景顏色
void gotoxy(int x,int y)//設(shè)置CMD窗口光標(biāo)位置
{
COORD coord;
coord.X = x;
coord.Y = y;
SetConsoleCursorPosition(GetStdHandle(STD_OUTPUT_HANDLE), coord);
}
void hide_cursor() //隱藏CMD窗口光標(biāo)
{
CONSOLE_CURSOR_INFO cci;
cci.bVisible = FALSE;
cci.dwSize = sizeof(cci);
HANDLE handle = GetStdHandle(STD_OUTPUT_HANDLE);
SetConsoleCursorInfo(handle, &cci);
}
void color(const unsigned short textColor) //自定義函根據(jù)參數(shù)改變顏色
{
if(textColor>0 && textColor<=15) //參數(shù)在0-15的范圍顏色
SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE), textColor); //用一個(gè)參數(shù),改變字體顏色
else //默認(rèn)的字體顏色是白色
SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE), 7);
}
//打印地圖
void map()
{
int x, y;
color(02);
/*開始打印棋盤格子*/
//打印橫向圖格
for(y = 2; y < high - 1; y+=2){
for(x = 1; x < width - 2; x+=2){
gotoxy(x , y);
printf("-+");
}
}
//打印豎向圖格
for(y = 1; y < high; y += 2) {
for(x = 2; x < width-2; x += 2){
gotoxy(x , y);
printf("|");
}
}
/*打印棋盤格子結(jié)束*/
/*開始打印圖框*/
//打印棋盤圖框
for (y = 0; y < high; y++)
{
for (x = 0; x < width; x+=2)
{
if (x == 0 || x == width - 2){
gotoxy(x, y);
printf("|");
}
if(y == 0 || y == high - 1 ){
gotoxy(x, y);
printf("--");
}
}
}
//打印右圖框
for(y = 0; y < high; y++){
for(x = width; x < WIDTH; x+=2){
if (x == WIDTH - 2){
gotoxy(x, y);
printf("|");
}
if(y == 0 || y == high - 1 ){
gotoxy(x, y);
printf("--");
}
}
}
//打印下圖框 y->high ~ HiGH-1 x->0 ~ WIDTH-2
for(y = high; y < HIGH; y++){
for(x = 0; x < WIDTH; x+=2){
if (x == 0 || x == WIDTH - 2){
gotoxy(x, y);
printf("|");
}
if(y == high || y == HIGH - 1 ){
gotoxy(x, y);
printf("--");
}
}
}
//打印下圖框內(nèi)容
gotoxy( 1, high+1);
printf(" 歡迎來到五子棋游戲!");
//打印右圖框內(nèi)容
gotoxy( width-1, 1);
printf("游戲說明:");
gotoxy( width-1, 3);
printf("1)X表示玩家一棋");
gotoxy( width-1, 4);
printf("子,而O表示玩家");
gotoxy( width-1, 5);
printf("二棋子");
gotoxy( width-1, 7);
printf("2)X先、O后,交替");
gotoxy( width-1, 8);
printf("下子,每次只能下");
gotoxy( width-1, 9);
printf("一子");
gotoxy( width-1, 11);
printf("3)棋子下在棋盤");
gotoxy( width-1, 12);
printf("的格子內(nèi),棋子下");
gotoxy( width-1, 13);
printf("定后,不得向其它");
gotoxy( width-1, 14);
printf("點(diǎn)移動(dòng)");
gotoxy( width-1, 16);
printf("4)最先連成五子");
gotoxy( width-1, 17);
printf("的一方即為獲勝");
gotoxy( width-1, 19);
printf("玩家一 移動(dòng)鍵:");
gotoxy( width-1, 20);
printf("w上 s下 a左 d右");
gotoxy( width-1, 21);
printf("下子: 空格鍵");
gotoxy( width-1, 23);
printf("玩家二 移動(dòng)鍵:");
gotoxy( width-1, 24);
printf("i上 k下 j左 l右");
gotoxy( width-1, 25);
printf("下子:回車鍵");
gotoxy( width+1, 27);
color(4);
printf("退出鍵: Y");
gotoxy( width+1, 29);
color(6);
printf("悔棋鍵: G");
/*打印圖框結(jié)束*/
color(02);
/*打印棋盤上的四個(gè)標(biāo)記點(diǎn)*/
gotoxy( 3*2+2 , 3*2+2);
printf("*");
gotoxy( (MAX_X-4)*2 , 3*2+2);
printf("*");
gotoxy( 3*2+2 , (MAX_Y-4)*2);
printf("*");
gotoxy( (MAX_X-4)*2 , (MAX_Y-4)*2);
printf("*");
/*打印結(jié)束*/
/*開始修邊*/
/*gotoxy(width - 1, 0);
printf(" ");
gotoxy(width - 1, high - 1);
printf(" ");*/
/*修邊結(jié)束*/
/*打印地圖完成*/
}
//打印動(dòng)態(tài)游戲說明
void game_Description()
{
//打印下圖框內(nèi)容
gotoxy( 1, high+1);
printf(" ");
if(player == player1){
gotoxy( 1, high+1);
color(2);
printf(" 玩家一下棋中...");
}else if(player == player2){
gotoxy( 1, high+1);
color(2);
printf(" 玩家二下棋中...");
}
}
//初始化游戲位置數(shù)據(jù)
void initMapState()
{
for(int i = 0 ; i < MAX_Y; i++){
for(int j = 0; j < MAX_X; j++){
pos[i][j] = 0;//初始狀態(tài)全為空
}
}
//注意 光標(biāo)的位置和存儲(chǔ)在數(shù)組中的位置是不同的
px = 7;
py = 7;
gotoxy(py*2+1,px*2+1);//初始位置
}
//數(shù)組記錄下對應(yīng)位置的狀態(tài)
void mapState(int qizi)
{ //2*px+1 = x //2*py+1 = y //px->0~14 //py->0~14
if(px >= MAX_X || px < 0 || py >= MAX_Y || py < 0)
return;//其他情況不可以記錄狀態(tài)
pos[px][py] = qizi;
}
//判斷是否可以落子
int isGoPlay()
{
if(px >= MAX_X || px < 0 || py >= MAX_Y || py < 0)
return 0;//其他情況不可以記錄狀態(tài)
if(pos[px][py] == emptyPlayer){//說明無子
return 1;
}else{//說明有子
return 0;
}
}
//以落子處為中心,判斷已經(jīng)落子后的棋盤是否五子相連
int hasGoPlay(int Player)
{ //分為兩部分,先記錄一部分的相同Player的個(gè)數(shù)
//再記錄下另余部分的個(gè)數(shù),相加為相連棋子總個(gè)數(shù)
int port1 = 0, port2 = 0;
int x, y, count;
//上下查找
x = px, y = py-1;
while(pos[x][y]==Player && y >= 0){
++port1;//上部分個(gè)數(shù)
--y;//上移
}
y = py+1;
while(pos[x][y]==Player && y < MAX_Y){
++port2;//下部分個(gè)數(shù)
++y;//下移
}
//計(jì)算總數(shù)
count = port1 + port2 + 1;
if(count >= 5) return 1;
//左右查找
port1 = 0, port2 = 0;
x = px-1, y = py;
while(pos[x][y]==Player && x >= 0){
++port1;//上部分個(gè)數(shù)
--x;//左移
}
x = px+1;
while(pos[x][y]==Player && x < MAX_X){
++port2;//下部分個(gè)數(shù)
++x;//右移
}
//計(jì)算總數(shù)
count = port1 + port2 + 1;
if(count >= 5) return 1;
//左上右下查找
port1 = 0, port2 = 0;
x = px-1, y = py-1;
while(pos[x][y]==Player && x >= 0 && y >= 0){
++port1;//上部分個(gè)數(shù)
--x;//左移
--y;//上移
}
x = px+1, y = py+1;
while(pos[x][y]==Player && x < MAX_X && y < MAX_Y){
++port2;//下部分個(gè)數(shù)
++x;//右移
++y;//下移
}
//計(jì)算總數(shù)
count = port1 + port2 + 1;
if(count >= 5) return 1;
//右上左下查找
port1 = 0, port2 = 0;
x = px+1, y = py-1;
while(pos[x][y]==Player && x < MAX_X && y >= 0){
++port1;//上部分個(gè)數(shù)
++x;//左移
--y;//上移
}
x = px-1, y = py+1;
while(pos[x][y]==Player && x >= 0 && y < MAX_Y){
++port2;//下部分個(gè)數(shù)
--x;//右移
++y;//下移
}
//計(jì)算總數(shù)
count = port1 + port2 + 1;
if(count >= 5) return 1;
return 0;
}
//落子 Player 1 2 0
void goPlay(int Player, Stack* p)
{
if(isGoPlay()){//說明可以落子
mapState(Player);//將對應(yīng)位置的情況記錄在數(shù)組中
if(hasGoPlay(Player)){//如果五子相連,則 gameover
gameOver_player = Player; //記錄此刻勝利玩家,結(jié)束游戲
}
/*入棧*/
push(p, px, py);
/*角色切換*/
if(Player == player1){
player = player2;//切換成玩家1
gotoxy(px*2+1, py*2+1 );//將光標(biāo)移動(dòng)到對應(yīng)位置
color(07);
printf("X");//打印玩家1
game_Description();// 動(dòng)態(tài)說明
}else if(Player == player2){
player = player1;//切換成另一個(gè)玩家2
gotoxy( px*2+1, py*2+1);//將光標(biāo)移動(dòng)到對應(yīng)位置
color(07);
printf("O");//打印玩家2
game_Description();// 動(dòng)態(tài)說明
}
}
}
//入棧
void push(Stack* p, int x, int y)
{
//將此刻的坐標(biāo)入棧
int top = p->top;
++p->top;//移動(dòng)棧針
p->x[top] = x;
p->y[top] = y;
return;
}
//出棧
void pop(Stack* p)
{
int x, y;
//出棧,移動(dòng)棧頂指針
//如果棧為空,則不彈出
if(p->top <= 0) return;
--p->top;
int top = p->top;
//記錄下彈出的位置
x = p->x[top];
y = p->y[top];
//在彈出位置打印空格
gotoxy(x*2+1, y*2+1);
printf(" ");
//抹除記錄
pos[x][y] = 0;
}
//移動(dòng)框
void yiDongKuang()
{
//打印移動(dòng)框
gotoxy(px*2, py*2+1);
color(11);
printf("[");
gotoxy(px*2+2, py*2+1);
printf("]");
//打印移動(dòng)框結(jié)束
if(pre_px != -1 && pre_py != -1){
if(pre_px > px && pre_py == py){//當(dāng)向左移動(dòng)時(shí)
//將上一個(gè)位置的右邊保持原樣
gotoxy(pre_px*2+2, pre_py*2+1);
color(2);
printf("|");
}else if(pre_px < px && pre_py == py){//當(dāng)向右移動(dòng)時(shí)
//將上一個(gè)位置的左邊保持原樣
gotoxy(pre_px*2, pre_py*2+1);
color(2);
printf("|");
}else{//當(dāng)向上下移動(dòng)時(shí)
//將上一個(gè)位置的左右邊保持原樣
gotoxy(pre_px*2+2, pre_py*2+1);
color(2);
printf("|");
gotoxy(pre_px*2, pre_py*2+1);
color(2);
printf("|");
}
}
pre_px = px;
pre_py = py;
}
//玩家1 移動(dòng)
void player1_move(Stack* p)
{
char key;
if (_kbhit())//檢測是否按鍵
{
fflush(stdin);
key = _getch();//保存按鍵
game_Description();//動(dòng)態(tài)說明
}
switch(key)
{
case 'w': py--;yiDongKuang();break;//上
case 'a': px--;yiDongKuang();break;//左
case 'd': px++;yiDongKuang();break;//右
case 's': py++;yiDongKuang();break;//下
case ' ': goPlay(player1, p);break;//落子
case 'y': gameOver_player = -2; gameOver();//退出游戲
case 'Y': gameOver_player = -2; gameOver();//退出游戲
case 'g': pop(p); pop(p); break;//悔棋
case 'G': pop(p); pop(p); break;//悔棋
default: break;
}
//限制光標(biāo)范圍
if(py < 0) py = MAX_Y-1;
else if(py >= MAX_Y) py = 0;
else if(px < 0) px = MAX_X-1;
else if(px >= MAX_X) px = 0;
gotoxy(2*py+1, 2*px+1);
}
//玩家2 移動(dòng)
void player2_move(Stack* p)
{
char key;
if (_kbhit())//檢測是否按鍵
{
fflush(stdin);
key = _getch();//保存按鍵
game_Description();//動(dòng)態(tài)說明
}
switch(key)
{
case 'i': py--;yiDongKuang();break;//上
case 'j': px--;yiDongKuang();break;//左
case 'l': px++;yiDongKuang();break;//右
case 'k': py++;yiDongKuang();break;//下
case '\r': goPlay(player2, p);break;//落子
case 'y': gameOver_player = -2; gameOver();//退出游戲
case 'Y': gameOver_player = -2; gameOver();//退出游戲
case 'g': pop(p); pop(p); break;//悔棋
case 'G': pop(p); pop(p); break;//悔棋
default: break;
}
//限制光標(biāo)范圍
if(py < 0) py = MAX_Y-1;
else if(py >= MAX_Y) py = 0;
else if(px < 0) px = MAX_X-1;
else if(px >= MAX_X) px = 0;
gotoxy(2*px+1, 2*py+1);
}
//創(chuàng)建空棧
Stack* createStack(){
//申請空間
Stack* p = (Stack* )malloc(sizeof(Stack));
//如果未申請到空間
if(p==NULL) return NULL;
p->top = 0;//初始化棧頂
return p;
}
//判斷游戲是否結(jié)束
int gameOver()
{ //gamerOver_player -1 表示繼續(xù)游戲 1 表示白方勝利 2 表示黑方勝利 0 表示平局
//五子相連 一方取勝 y->high ~ HiGH-1 x->0 ~ WIDTH-2
if(gameOver_player == -1){
return 1;
}else if(gameOver_player == player1){//白方勝利
gotoxy( 1, high+1);
printf("玩家1勝利?。?!");
return 0;
}else if(gameOver_player == player2){//黑方勝利
gotoxy( 1, high+1);
printf("玩家2勝利?。。?);
return 0;
}else if(gameOver_player == emptyPlayer){//棋盤滿棋 平局
gotoxy( 1, high+1);
printf("平局!?。?);
return 0;
}else if(gameOver_player == Unplayer){//中途退出
gotoxy( 1, high+1);
printf("正在退出游戲中...");
exit(1);
}
return 1;
}
int main(){
//調(diào)整游戲框
system("mode con cols=48 lines=35");
//打印地圖
map();
//初始化游戲位置數(shù)據(jù)
initMapState();
//創(chuàng)建空棧
Stack* p = createStack();
//隱藏光標(biāo)
hide_cursor();
//游戲循環(huán) 控制移動(dòng)
while(gameOver()){
//不斷調(diào)換人物
if(player == player1)
player1_move(p);// 切換玩家1
else if(player == player2)
player2_move(p);// 切換玩家2
}
free(p);
}以上就是本文的全部內(nèi)容,希望對大家的學(xué)習(xí)有所幫助,也希望大家多多支持腳本之家。
相關(guān)文章
C語言函數(shù)調(diào)用底層實(shí)現(xiàn)原理分析
這篇文章主要介紹了C語言函數(shù)調(diào)用底層實(shí)現(xiàn)原理,具有很好的參考價(jià)值,希望對大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2023-02-02
C語言 volatile與const同時(shí)使用應(yīng)注意的問題
“volatile”的含義是“請不要做沒譜的優(yōu)化,這個(gè)值可能變掉的”,而并非“你可以修改這個(gè)值”。因此,它們本來就不是矛盾的2013-09-09
QT使用QML實(shí)現(xiàn)地圖繪制虛線的示例代碼
QML提供了MapPolyline用于在地圖上繪制線段,這篇文章主要為大家詳細(xì)介紹了QT如何使用QML實(shí)現(xiàn)在地圖上繪制虛線,需要的小伙伴可以參考一下2023-07-07
C語言FlappyBird飛揚(yáng)的小鳥實(shí)現(xiàn)開發(fā)流程
因?yàn)樵诩艺撕枚嗵欤S手玩了下自己以前做的一些小游戲,說真的,有幾個(gè)游戲做的是真的劣質(zhì),譬如 flappybird 真的讓我難以忍受,于是重做了一波分享給大家2022-11-11
C++實(shí)現(xiàn)獲取系統(tǒng)時(shí)間的方法小結(jié)
這篇文章主要為大家詳細(xì)介紹了使用C++實(shí)現(xiàn)獲取系統(tǒng)時(shí)間的一些常用方法,文中的示例代碼講解詳細(xì),具有一定的借鑒價(jià)值,有需要的小伙伴可以了解下2024-03-03
vc控制臺(tái)程序關(guān)閉事件時(shí)的處理方式及注意點(diǎn)詳解
在本篇文章里小編給大家整理的是一篇關(guān)于vc控制臺(tái)程序關(guān)閉事件時(shí)的正確處理方式的相關(guān)知識點(diǎn)內(nèi)容,對此有需求的朋友們可以參閱下。2021-12-12
C++?使用?new?創(chuàng)建二維數(shù)組實(shí)例
這篇文章主要介紹了C++?使用?new?創(chuàng)建二維數(shù)組實(shí)例的相關(guān)資料,需要的朋友可以參考下2023-01-01

