欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

使用C語言實現(xiàn)五子棋游戲

 更新時間:2022年08月03日 16:48:37   作者:7昂7.  
這篇文章主要為大家詳細(xì)介紹了使用C語言實現(xiàn)五子棋游戲,文中示例代碼介紹的非常詳細(xì),具有一定的參考價值,感興趣的小伙伴們可以參考一下

本文實例為大家分享了C語言實現(xiàn)五子棋游戲的具體代碼,供大家參考,具體內(nèi)容如下

一、實現(xiàn)的目的和意義

1、鞏固和加深對c語言知識的理解
2、學(xué)會使用編譯器的各種調(diào)試
3、提高解決實際問題的能力

二、實現(xiàn)內(nèi)容描述

實現(xiàn)簡單的人人對戰(zhàn)五子棋,此設(shè)計用的是C語言去實現(xiàn)

三、實現(xiàn)原理

采用二位數(shù)組保存棋盤信息,棋盤上面的任何一個位置,里頭可以放三個信息:

1、空
2、用戶1的落子
3、用戶2的落子

下棋就是在二維數(shù)組種找對應(yīng)的空位置,進(jìn)行落子,落完之后立即就要判斷落子位置是否有五字連珠,從而判斷誰數(shù)輸誰贏。每走一次棋會有四種情況:

*用戶1贏
*用戶2贏
*平局(這里說的平局是棋盤被占滿的情況)
*沒有出結(jié)果 意思就是時此用戶沒贏 下個用繼續(xù)去下棋

四、實現(xiàn)模塊五子棋實現(xiàn)分為三大模塊

文件名                       作用
five_chress.h       五子棋的函數(shù)聲明,頭文件聲明等
five_chress.c       五子棋函數(shù)接口的實現(xiàn)
main.c              五子棋函數(shù)測試功能

五、模塊代碼分析

1、five_chress.h

#pragma once
#include <stdio.h>
#include <string.h>
#include<Windows.h>
#define ROW 10//數(shù)組號行號 按需求調(diào)整
#define COL 10//數(shù)組列數(shù) 按需求調(diào)整
#define PLAYER1 1//玩家編號,默認(rèn)棋盤數(shù)據(jù)是0,玩家1落子,該位置被改成1
#define PLAYER2 2//玩家編號,默認(rèn)棋盤數(shù)據(jù)是0,玩家2落子,該位置被改成2
#define NEXT ? ? ? ?0//游戲繼續(xù)
#define PLAYER1_WIN 1//玩家1贏
#define PLAYER2_WIN 2//玩家2贏
#define DRAW ? ? ? ?3//平局

? ?enum Dir{
?? ?LEFT,
?? ?RIGHT,
?? ?UP,
?? ?DOWN,
?? ?LEFT_UP,
?? ?LEFT_DOWN,
?? ?RIGHT_UP,
?? ?RIGHT_DOWN
? ? };//用枚舉去表示4個方向,上下,左右,左上右下,右上左下,統(tǒng)計用戶當(dāng)前棋子四個方向的棋數(shù)是否為大于等于5
? ? void Menu();//實現(xiàn)菜單
? ? void Game();//構(gòu)建游戲入口Game()函數(shù) ? ? ?

2、five_chress.c

#include "five_chress.h"

int x = 0;
int y = 0;

void Menu()
{
?? ?printf("############################\n");
?? ?printf("## 1. Play ? ? ? ?0. Exit ##\n");
?? ?printf("############################\n");
?? ?printf("Please Select# ");
}

//按照x,y作為起點,按照特定的方向,求連續(xù)相對的最大格式
int ChessCount(int board[][COL], int row, int col, enum Dir d)
{
?? ?int _x = x - 1; //從1
?? ?int _y = y - 1; //從1

?? ?int count = 0;
?? ?while (1){
?? ??? ?switch (d){
?? ??? ?case LEFT://從當(dāng)前位置向左移動統(tǒng)計 橫坐標(biāo)不變 縱坐標(biāo)變了 所以是y--
?? ??? ??? ?_y--;
?? ??? ??? ?break;
?? ??? ?case RIGHT://從當(dāng)前位置向右移動統(tǒng)計 橫坐標(biāo)不變 縱坐標(biāo)變了 所以是_y++
?? ??? ??? ?_y++;
?? ??? ??? ?break;
?? ??? ?case UP://從當(dāng)前位置向上移動統(tǒng)計 縱坐標(biāo)不變 橫坐標(biāo)變了 所以是_x--
?? ??? ??? ?_x--;
?? ??? ??? ?break;
?? ??? ?case DOWN://從當(dāng)前位置向下移動統(tǒng)計 縱坐標(biāo)不變 橫坐標(biāo)變了 所以是_x++
?? ??? ??? ?_x++;
?? ??? ??? ?break;
?? ??? ?case LEFT_UP://從當(dāng)前位置向左上移動統(tǒng)計 縱,橫變都變了 所以是_x--,_y--
?? ??? ??? ?_x--, _y--;
?? ??? ??? ?break;
?? ??? ?case LEFT_DOWN://從當(dāng)前位置左下移動統(tǒng)計 縱,橫坐標(biāo)都變了 所以是_x++,_y--
?? ??? ??? ?_x++, _y--;
?? ??? ??? ?break;
?? ??? ?case RIGHT_UP://從當(dāng)前位置右上移動統(tǒng)計 縱,橫坐標(biāo)都變了 所以是_x--,_y++-
?? ??? ??? ?_x--, _y++;
?? ??? ??? ?break;
?? ??? ?case RIGHT_DOWN://從當(dāng)前位置右下移動統(tǒng)計 縱,橫坐標(biāo)都變了 所以是_x++,_y++
?? ??? ??? ?_x++, _y++;
?? ??? ??? ?break;
?? ??? ?default:
?? ??? ??? ?//Do Nothing
?? ??? ??? ?break;
?? ??? ?}
?? ??? ?if (_x < 0 || _x > row - 1 || _y < 0 || _y > col - 1){
?? ??? ??? ?break;/表示越界了就停止
?? ??? ?}
?? ??? ?//合法
?? ??? ?if (board[x - 1][y - 1] == board[_x][_y]){
?? ??? ??? ?count++;//統(tǒng)計從舊位置出發(fā)統(tǒng)計和他一樣的個數(shù)
?? ??? ?}
?? ??? ?else{
?? ??? ??? ?break;//如果碰到不一樣的就終止循環(huán)
?? ??? ?}
?? ?}
?? ?return count;//返回統(tǒng)計個數(shù)
}

//4種情況
//NEXT:表明要繼續(xù)
//PLAYER1_WIN: 用戶1贏了
//PLAYER2_WIN:用戶2贏了
//DRAW: 平局
int IsOver(int board[][COL], int row, int col)
{
?? ?
?? ?int count1 = ChessCount(board, row, col, LEFT) + ChessCount(board, row, col, RIGHT) + 1; //?
?? ?int count2 = ChessCount(board, row, col, UP) + ChessCount(board, row, col, DOWN) + 1; //?
?? ?int count3 = ChessCount(board, row, col, LEFT_UP) + ChessCount(board, row, col, RIGHT_DOWN) + 1; //?
?? ?int count4 = ChessCount(board, row, col, LEFT_DOWN) + ChessCount(board, row, col, RIGHT_UP) + 1; //?

?? ?if (count1 >= 5 || count2 >= 5 || count3 >= 5 || count4 >= 5){
?? ??? ?//有五子連珠
?? ??? ?//一定有人贏
?? ??? ?//x, y
?? ??? ?if (board[x - 1][y - 1] == PLAYER1){
?? ??? ??? ?return PLAYER1_WIN;
?? ??? ?}
?? ??? ?else{
?? ??? ??? ?return PLAYER2_WIN;
?? ??? ?}
?? ?}

?? ?int i = 0;
?? ?for (; i < row; i++){
?? ??? ?int j = 0;
?? ??? ?for (; j < col; j++){
?? ??? ??? ?if (board[i][j] == 0){
?? ??? ??? ??? ?return NEXT;//當(dāng)前位置還沒有被填寫棋盤不滿 當(dāng)前用戶沒有贏返回next ?讓下個用戶繼續(xù)下
?? ??? ??? ?}
?? ??? ?}
?? ?}

?? ?return DRAW;//最后一種情況棋盤滿了 為平局
}

void ShowBoard(int board[][COL], int row, int col)
{
?? ?//printf("\e[1;1H\e[2J");這是linux環(huán)境下用的清屏
?? ?//講數(shù)組內(nèi)容,進(jìn)行可視化
?? ?system("cls");//vs環(huán)境下用的清屏
?? ?
?? ?int i = 0;
?? ?for (i=1; i <= col; i++){
?? ??? ?printf("%3d", i);
?? ?}
?? ?printf("\n");

?? ?for (i = 0; i < row; i++){
?? ??? ?int j = 0;
?? ??? ?printf("%2d",i + 1 );
?? ??? ?for (; j < col; j++){
?? ??? ??? ?if (board[i][j] == 0){
?? ??? ??? ??? ?printf(" . ");
?? ??? ??? ?}
?? ??? ??? ?else if (board[i][j] == PLAYER1){
?? ??? ??? ??? ?printf(" x ");
?? ??? ??? ?}
?? ??? ??? ?else{
?? ??? ??? ??? ?printf (" y ");
?? ??? ??? ?}
?? ??? ?}
?? ??? ?printf("\n");
?? ?}
}

void PlayerMove(int board[][COL], int row, int col, int who)
{
?? ?while (1){
?? ??? ?printf("Player[%d] Please Enter Your Pos# ", who);
?? ??? ?scanf("%d %d", &x, &y);
?? ??? ?if (x < 1 || x > row || y < 1 || y > col){
?? ??? ??? ?printf("Pos Is Not Right!\n");
?? ??? ??? ?continue;
?? ??? ?}
?? ??? ?else if (board[x - 1][y - 1] != 0){
?? ??? ??? ?printf("Pos Is Occupied!\n");
?? ??? ??? ?continue;
?? ??? ?}
?? ??? ?else{
?? ??? ??? ?//合法性,去重
?? ??? ??? ?board[x - 1][y - 1] = who;
?? ??? ??? ?break;
?? ??? ?}
?? ?}
}

void Game()
{
?? ?int board[ROW][COL];
?? ?memset(board, 0, sizeof(board));
?? ?int result = NEXT;
?? ?do{
?? ??? ?ShowBoard(board, ROW, COL);//顯示棋盤
?? ??? ?PlayerMove(board, ROW, COL, PLAYER1);//Player1先走
?? ??? ?result = IsOver(board, ROW, COL);//判斷游戲是否結(jié)束
?? ??? ?if (NEXT != result){
?? ??? ??? ?break;//如果返回值不等于NEXT就跳出循環(huán) 說明當(dāng)前用戶贏了或者平局 如果=NEXT 下個用戶繼續(xù)下
?? ??? ?}
?? ??? ?ShowBoard(board, ROW, COL);//同上
?? ??? ?PlayerMove(board, ROW, COL, PLAYER2);
?? ??? ?result = IsOver(board, ROW, COL);
?? ??? ?if (NEXT != result){
?? ??? ??? ?break;
?? ??? ?}
?? ?} while (1);
?? ?//p1 win, p2 win, draw
?? ?switch (result){
?? ?case PLAYER1_WIN:
?? ??? ?ShowBoard(board, ROW, COL);
?? ??? ?printf("恭喜用戶1,你已經(jīng)贏了!\n");
?? ??? ?break;
?? ?case PLAYER2_WIN:
?? ??? ?printf("恭喜用戶2,你已經(jīng)贏了!\n");
?? ??? ?break;
?? ?case DRAW:
?? ??? ?printf("平局\n");
?? ??? ?break;
?? ?default:
?? ??? ?//do nothing!
?? ??? ?break;
?? ?}
}

分析:

我們要先構(gòu)建游戲入口void game()函數(shù)在里面構(gòu)建上層本調(diào)用框架 例如一開始初始化數(shù)組把每個位置都置為0,然后構(gòu)建調(diào)用框架:

1、我們要保存二位數(shù)組并可視化 就要構(gòu)建ShowBoard函數(shù);
2、之后 我們要讓用戶下棋 就要構(gòu)建PlayerMove()函數(shù)
3、第一個用戶下完之后就要立馬判斷當(dāng)前用戶是否贏,因為落子和判定是強(qiáng)相關(guān)的 這時候要構(gòu)建 IsOver()函數(shù)
如果此用戶沒贏 那二個用戶繼續(xù)下。
當(dāng)我們這些函數(shù)邏輯都明確好的時候 就用分而治之思想 ,實現(xiàn)他們的功能。
* 1、ShowBoard()函數(shù)里面我用到了一個c語言里面的清屏函數(shù)printf(“cls”);引上頭文件window.h,這個的作用是在固定地方刷新視圖,把上次的視圖清理掉 ,顯示當(dāng)前位置視圖。
后面就打印視圖的內(nèi)容。用戶一和用戶二可以用字符表示,也可以用圓圈圖案表示這個圖案可以在網(wǎng)上找復(fù)制一下就可
*2、 Playermove()函數(shù)讓用戶下棋,里面先考慮它的合法性 ,不能越界和重復(fù),再然后用我們在five_chrsss.h文件定義宏來賦值 ,賦完之后再終止循環(huán)。
*3、 Isover()函數(shù)里面是讓我們判斷誰輸誰贏 換句話游戲是否結(jié)束。游戲結(jié)束標(biāo)志是分為四種情況。用戶一贏,用戶二贏,平局,繼續(xù)。前兩種情況則需要判斷從當(dāng)前位置出發(fā) 沿四個方向當(dāng)前用戶棋的個數(shù)是否為大于等于5,在判斷一下是哪個用戶的棋 就返回哪個用戶。 而這判斷需要在構(gòu)建并調(diào)用ChressCount()函數(shù)去統(tǒng)計當(dāng)前用戶的個數(shù)是否大于等于5,有4個方向,例如上和下為一個方向,左和右為一個方向,左上和右下為一個方向,右上和左下為一個方向,分別各自相加之后在加上1就是當(dāng)前的棋,如果滿足這個4個方向大于等于5的一個條件,我們就能知道一定有人贏,否則在繼續(xù)判斷周圍是否有空位置,有則返回NEXT讓下個用戶繼續(xù)下,沒有則返回平局*ChressCoun()函數(shù)具體分析請看代碼塊

這些函數(shù)實現(xiàn)完之后再在Game()函數(shù)里面來個Switch循環(huán),來結(jié)收宏 去打印誰贏 還是平局。

3、main.c

#include "five_chress.h"

int main()
{
?? ?int quit = 0;
?? ?int select = 0;
?? ?while (!quit){
?? ??? ?Menu();
?? ??? ?scanf("%d", &select);
?? ??? ?switch (select){
?? ??? ?case 1:
?? ??? ??? ?Game();
?? ??? ??? ?break;
?? ??? ?case 0:
?? ??? ??? ?quit = 1;
?? ??? ??? ?printf("ByeBye!\n");
?? ??? ??? ?break;
?? ??? ?default:
?? ??? ??? ?printf("Enter Error, Try Again!\n");
?? ??? ??? ?break;
?? ??? ?}
?? ?}

?? ?return 0;
}

main函數(shù)作為測試入口,相比較里面的邏輯是很簡單的,創(chuàng)建一個菜單函數(shù)和調(diào)用一個Game函數(shù),再增添點其他的內(nèi)容。

六、實現(xiàn)結(jié)果

七、總結(jié)

實現(xiàn)五子棋給我最大的體會是應(yīng)用比理論學(xué)習(xí)難得多,首先要邏輯清楚,也會涉及到各種實際問題,但是加深了我對知識的理解和運(yùn)用,也知道了只有多練習(xí) 多寫代碼才能更好的提升編程技術(shù)。同時我也學(xué)到了實現(xiàn)一個復(fù)雜的項目時,先去構(gòu)建一個框架,一個清晰的邏輯。再去逐個擊破每個問題,要學(xué)會用分而治之的思想去解決問題。

以上就是本文的全部內(nèi)容,希望對大家的學(xué)習(xí)有所幫助,也希望大家多多支持腳本之家。

相關(guān)文章

最新評論