最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

C#實現(xiàn)五子棋游戲

 更新時間:2021年01月10日 14:22:19   作者:steveliu13  
這篇文章主要為大家詳細(xì)介紹了C#實現(xiàn)五子棋游戲,文中示例代碼介紹的非常詳細(xì),具有一定的參考價值,感興趣的小伙伴們可以參考一下

曾經(jīng)自學(xué)C#做計算機(jī)圖形學(xué)的作業(yè),GDI+畫圖確實好用,目前在找.NET的實習(xí),嘗試做了一個最基本的五子棋,復(fù)習(xí)一下C#的基本語法,目前只能當(dāng)跟基友一起玩的單機(jī)小游戲,之后再加入AI和聯(lián)網(wǎng)對戰(zhàn)功能。目前我還是小菜鳥,過程設(shè)計和代碼有不合理或者能優(yōu)化的地方歡迎各位大神指正。

首先是界面設(shè)計,最后就是這樣,控件一共有一個PictureBox;一個開始Button,命名為btnStart;一個重置Button,命名為btnReset;一個Label,用于顯示游戲狀態(tài)。

五子棋界面

然后是各基本類。新建一個MainSize類用于存放界面上的可能用到的參數(shù),主框體大小520*460,棋盤是一個PictureBox控件,大小401*401,棋盤20行20列,每個格子邊長20,棋子直徑16。新建一個ChessBoard類表示棋盤,有一個靜態(tài)函數(shù)DrawBoard。之前做計算機(jī)圖形學(xué)作業(yè)畫函數(shù)時用到的畫坐標(biāo)系方法在這里同樣適用,函數(shù)代碼如下。

class ChessBoard
 {

 static readonly Color color = Color.Black;
 static readonly float penWid = 1.0f;
 static readonly Pen pen = new Pen(color, penWid); 

 public static void DrawCB(Graphics gra,PictureBox pic)
 {
  //每排數(shù)量
  int horC = MainSize.CBWid / MainSize.CBGap;
  //間隔
  int gap = MainSize.CBGap;
  Image img = new Bitmap(MainSize.CBWid, MainSize.CBHei);
  gra = Graphics.FromImage(img);
  gra.Clear(Color.White);
  gra.DrawRectangle(pen, 0, 0, MainSize.CBWid, MainSize.CBHei);
  //畫棋盤
  for (int i = 0; i < horC; i++)
  {
  gra.DrawLine(pen, 0, i * gap, MainSize.CBWid, i * gap);
  gra.DrawLine(pen, i * gap, 0, i * gap, MainSize.CBHei);
  }
  gra.DrawLine(pen, 0, horC * gap, MainSize.CBWid, horC * gap - 1);
  gra.DrawLine(pen, horC * gap - 1, 0, horC * gap, MainSize.CBHei);
  pic.Image = img;
 }

 }

還有一個基本類Chess,用來表示棋子,有一個靜態(tài)函數(shù)DrawChess,代碼如下。這里代碼有點(diǎn)亂,寫的時候沒加注釋。bool型變量用于表示下棋的雙方,pen1和pen2用于繪制雙方的棋子,顏色設(shè)置為紅藍(lán),因為自古紅藍(lán)出CP【其實是本來想用黑白的但picturebox背景白色再畫白色棋子就看不出來】。整型變量nexX和newY用于表示棋子在棋盤上的坐標(biāo),根據(jù)四舍五入就近原則落點(diǎn)。這里的四舍五入我花了很長時間,寫了很長的一段判斷代碼但都會出錯,最后借鑒了github上Xu Pu同學(xué)的數(shù)據(jù)結(jié)構(gòu)假期作業(yè)中的方法才完成了這個函數(shù),在此感謝這位同學(xué)~

class Chess
 {
 public static void DrawChess(bool type,PictureBox pic,Graphics graphic,MouseEventArgs e)
 {
  graphic = pic.CreateGraphics();
  Pen pen1 = new Pen(Color.Red, 1);
  Brush bru1 = new SolidBrush(Color.Red);
  Pen pen2 = new Pen(Color.Blue, 1);
  Brush bru2 = new SolidBrush(Color.Blue);
  int newX = (int)((e.X + MainSize.CBGap / 2) / MainSize.CBGap) * MainSize.CBGap - MainSize.ChessRadious / 2;
  int newY = (int)((e.Y + MainSize.CBGap / 2) / MainSize.CBGap) * MainSize.CBGap - MainSize.ChessRadious / 2;
  if (type)
  {
  graphic.DrawEllipse(pen1, newX, newY, MainSize.ChessRadious, MainSize.ChessRadious);
  graphic.FillEllipse(bru1, newX, newY, MainSize.ChessRadious, MainSize.ChessRadious);
  }
  if (!type)
  {
  graphic.DrawEllipse(pen2, newX, newY, MainSize.ChessRadious, MainSize.ChessRadious);
  graphic.FillEllipse(bru2, newX, newY, MainSize.ChessRadious, MainSize.ChessRadious);
  }
  graphic.Dispose();
 }

 }

最后是主程序,一共設(shè)置了四個全局變量,Graphics graphic用于畫圖,bool type用于表示下棋雙方,bool start表示游戲是否開始,二維數(shù)組ChessBack用于模擬下棋場景并進(jìn)行計算。

主程序的構(gòu)造函數(shù)對主框體和PictureBox的大小進(jìn)行初始化,在Form1_Load函數(shù)中添加函數(shù)InitializeThis()對游戲進(jìn)行初始化,包括將ChessBack數(shù)組全部置0,type設(shè)為true,start設(shè)為false,繪制棋盤,按鍵開始的enabled屬性設(shè)為true,按鍵重置設(shè)為false。

按鍵開始和重置的功能較為簡單,代碼如下。

private void btnStart_Click(object sender, EventArgs e)
 {
  start = true;
  label1.Text = "游戲開始!";
  btnStart.Enabled = false;
  btnReset.Enabled = true;
 }

 private void btnReset_Click(object sender, EventArgs e)
 {

  if (MessageBox.Show("確定要重新開始?", "提示", MessageBoxButtons.YesNo) == DialogResult.Yes)
  {    
  InitializeThis();
  }
 }

最重要的部分是點(diǎn)擊picturebox的函數(shù),先判斷游戲是否開始,否則不會有反應(yīng)。游戲開始后點(diǎn)擊即可落子,并修改ChessBack矩陣,紅色為1,藍(lán)色為2,如果已經(jīng)有棋子則返回,即落子失敗。如果棋盤已滿但沒有分出勝負(fù)則彈出平局的提示框并給出提示。之后判斷是否分出勝負(fù),添加函數(shù)bool Victory(int bx,int by),分出勝負(fù)后提示勝利,如果沒有則返回。最后換人,type=!type即可,然后修改label的文字表面到哪一方落子了。代碼如下。

private void pictureBox1_MouseClick(object sender, MouseEventArgs e)
 {
  if (start)
  {
  //在計算矩陣中的位置
  int bX = (int)((e.X + MainSize.CBGap / 2) / MainSize.CBGap);
  int bY = (int)((e.Y + MainSize.CBGap / 2) / MainSize.CBGap);
  //防止在同一個位置落子
  if (ChessBack[bX, bY] != 0)
   return;
  Chess.DrawChess(type, pictureBox1, graphic, e);
  ChessBack[bX,bY] = type?1:2;
  //判斷棋盤是否滿了

  if (IsFull() && !Victory(bX,bY))
  {
   if (MessageBox.Show("游戲結(jié)束,平局") == DialogResult.OK)
   InitializeThis();
   return;
  }
  //判斷勝利
  if (Victory(bX,bY))
  {
   string Vic = type ? "紅" : "藍(lán)";
   if (MessageBox.Show(Vic + "方勝利!") == DialogResult.OK)
   InitializeThis();
   return; 
  }

  //換人
  type = !type;
  label1.Text = type ? "紅方's trun!" : "藍(lán)方's turn!";
  }
  else
  return;
 }

判斷勝負(fù)的函數(shù)有點(diǎn)復(fù)雜,我自己是用遞歸的方式判斷,先寫了一個橫向的進(jìn)行測試,如果橫向兩端的值與當(dāng)前值相同則變量count++,最后返回count的值,如果>4則表示勝利。但是這個函數(shù)運(yùn)行出錯,顯示為stackoverflow,但我不知道錯誤在哪,只好換一種判斷方法。后來才想明白兩端的值都是0則會溢出,應(yīng)該判斷兩端的值是否為1或2而不是當(dāng)前值。此處借鑒了實驗樓網(wǎng)站上的C語言版五子棋的判斷勝負(fù)方式,從當(dāng)前落子的矩陣中,橫豎斜4個方向任意一個方向有連續(xù)5個數(shù)的值與當(dāng)前的值相同則勝利,實現(xiàn)也不復(fù)雜,細(xì)分為三個函數(shù)實現(xiàn)。代碼如下。

#region 判斷勝利
 private bool Victory(int bx,int by)
 {
  if (HorVic(bx, by))
  return true;
  if (VerVic(bx, by))
  return true;
  if (Vic45(bx, by))
  return true;
  else
  return false;
 }

 private bool Vic45(int bx, int by)
 {

  int b1 = (bx - 4) > 0 ? bx - 4 : 0;
  int b2 = (by - 4) > 0 ? by - 4 : 0;
  //int buttom = b1 > b2 ? b2 : b1;
  int val = ChessBack[bx, by];
  for (int i = b1,j=b2; i < 16&&j<16; i++,j++)
  {
  if (ChessBack[i, j] == val && ChessBack[i + 1, j + 1] == val &&
   ChessBack[i + 2, j + 2] == val && ChessBack[i + 3, j + 3] == val
   && ChessBack[i + 4, j + 4] == val)
   return true;
  }
  for (int i = b1, j = b2; i < 16 && j < 16; i++, j++)
  {
  if (ChessBack[i, j] == val && ChessBack[i + 1, j - 1] == val &&
   ChessBack[i + 2, j - 2] == val && ChessBack[i + 3, j - 3] == val
   && ChessBack[i - 4, j - 4] == val)
   return true;
  }
  return false;
 }

 private bool VerVic(int bx, int by)
 {
  int buttom = (by - 4) > 0 ? by - 4 : 0;
  int val = ChessBack[bx, by];
  for (int i = buttom; i < 16; i++)
  {
  if (ChessBack[bx, i] == val && ChessBack[bx, i+1] == val &&
   ChessBack[bx, i+2] == val && ChessBack[bx ,i+3] == val
   && ChessBack[bx, i+4] == val)
   return true;
  }
  return false;
 }

 private bool HorVic(int bx, int by)
 {
  int left = (bx-4)>0?bx-4:0;
  int val = ChessBack[bx,by];
  for (int i = left; i < 16; i++)
  {
  if (ChessBack[i, by] == val && ChessBack[i + 1, by] == val &&
   ChessBack[i + 2, by] == val && ChessBack[i + 3, by] == val
   && ChessBack[i + 4, by] == val)
   return true;
  }
  return false;
 }
 #endregion

完成后進(jìn)行測試,都沒有問題,即認(rèn)為大功告成了??偨Y(jié)了一下編寫過程中問題,變量命名不太好,type,start等變量容易與關(guān)鍵詞混淆;主函數(shù)代碼行數(shù)還是太多,不方便閱讀,或許應(yīng)該把判定勝負(fù)和判定棋盤是否已滿也移到棋盤類中;之后添加新游戲模式不方便,比如添加AI和聯(lián)機(jī)對戰(zhàn),需要修改的代碼有點(diǎn)多,個人想法是分別新建一個帶AI的框體和聯(lián)機(jī)的框體,然后修改基本類,在這種情況下最大化的代碼復(fù)用。

回想一個這個小程序編寫并不復(fù)雜,但我花了很多時間在改錯上,落子的函數(shù)和判斷勝利的函數(shù)花的時間最多,事前用筆進(jìn)行一下簡單的演算再寫或許能省一點(diǎn)時間。這是我的第一篇博客,暫時當(dāng)實驗報告來寫吧,雖然是出于興趣做的,但還是希望各位大神能指出不足,給出建議,我會虛心學(xué)習(xí)的。最后再次感謝實驗樓網(wǎng)站【不是軟廣】和github上的Xu Pu同學(xué),還有各位看到最后的朋友們~

更多有趣的經(jīng)典小游戲?qū)崿F(xiàn)專題,分享給大家:

C++經(jīng)典小游戲匯總

python經(jīng)典小游戲匯總

python俄羅斯方塊游戲集合

JavaScript經(jīng)典游戲 玩不停

java經(jīng)典小游戲匯總

javascript經(jīng)典小游戲匯總

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

相關(guān)文章

  • .Net多進(jìn)程通信共享內(nèi)存映射文件Memory?Mapped

    .Net多進(jìn)程通信共享內(nèi)存映射文件Memory?Mapped

    這篇文章主要介紹了.Net多進(jìn)程通信共享內(nèi)存映射文件Memory?Mapped的使用示例,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪
    2022-04-04
  • C#.Net基于正則表達(dá)式抓取百度百家文章列表的方法示例

    C#.Net基于正則表達(dá)式抓取百度百家文章列表的方法示例

    這篇文章主要介紹了C#.Net基于正則表達(dá)式抓取百度百家文章列表的方法,結(jié)合實例形式分析了C#獲取百度百家文章內(nèi)容及使用正則表達(dá)式匹配標(biāo)題、內(nèi)容、地址等相關(guān)操作技巧,需要的朋友可以參考下
    2017-08-08
  • 深入分析WPF客戶端讀取高清圖片卡以及縮略圖的解決方法詳解

    深入分析WPF客戶端讀取高清圖片卡以及縮略圖的解決方法詳解

    本篇文章是對WPF客戶端讀取高清圖片卡以及縮略圖的解決方法進(jìn)行了詳細(xì)的分析介紹,需要的朋友參考下
    2013-05-05
  • C#調(diào)用js庫的方法示例代碼

    C#調(diào)用js庫的方法示例代碼

    這篇文章主要介紹了C#調(diào)用js庫的方法,本文結(jié)合示例代碼給大家介紹的非常詳細(xì),對大家的學(xué)習(xí)或工作具有一定的參考借鑒價值,需要的朋友可以參考下
    2023-01-01
  • C# 基礎(chǔ)入門--變量

    C# 基礎(chǔ)入門--變量

    本文主要介紹了C#中變量的基礎(chǔ)知識,具有很好的參考價值。下面跟著小編一起來看下吧
    2017-03-03
  • C#?EventHander的具體使用

    C#?EventHander的具體使用

    EventHandler是一種用于處理事件的委托類型,它在C#中用于處理沒有特定參數(shù)或返回值的簡單事件,本文就來介紹C#?EventHander的具體使用,感興趣的可以了解一下
    2025-01-01
  • C#難點(diǎn)逐個擊破(2):out返回參數(shù)

    C#難點(diǎn)逐個擊破(2):out返回參數(shù)

    之前提到ref是將原方法中的參數(shù)影響的結(jié)果返回到調(diào)用它的方法中,out與ref類似,相比之下,ref傳遞參數(shù)的地址,out是返回值。
    2010-02-02
  • C#從文件流讀取xml文件到DataSet并顯示的方法

    C#從文件流讀取xml文件到DataSet并顯示的方法

    這篇文章主要介紹了C#從文件流讀取xml文件到DataSet并顯示的方法,實例分析了C#操作XML文件的技巧與DataSet的使用方法,需要的朋友可以參考下
    2015-04-04
  • C#中的DateTime是值類型還是引用類型

    C#中的DateTime是值類型還是引用類型

    近期遇到了DateTime到底是值類型還是引用類型的疑惑,順勢較深入地了解一下DateTime相關(guān)的內(nèi)容,大家有需要的朋友可以參考下
    2017-04-04
  • Unity?使用tiledmap解析地圖的詳細(xì)過程

    Unity?使用tiledmap解析地圖的詳細(xì)過程

    這篇文章主要介紹了Unity?使用tiledmap解析地圖,本文通過圖文實例相結(jié)合給大家介紹的非常詳細(xì),對大家的學(xué)習(xí)或工作具有一定的參考借鑒價值,需要的朋友可以參考下
    2022-04-04

最新評論

西青区| 健康| 徐水县| 临漳县| 吴川市| 西贡区| 商水县| 交城县| 邛崃市| 阿荣旗| 桑日县| 牡丹江市| 漠河县| 铜鼓县| 涪陵区| 和龙市| 朝阳市| 金山区| 青田县| 南华县| 浠水县| 西青区| 南开区| 白沙| 施秉县| 扎兰屯市| 孙吴县| 六枝特区| 即墨市| 永登县| 灵武市| 财经| 沾化县| 化德县| 苏尼特左旗| 冷水江市| 丰台区| 鲁甸县| 宁化县| 甘肃省| 舒兰市|