前提
リバーシのプログラムを作っています。
https://www.webcyou.com/?p=6997
↑このサイトをベースにして、Computer.csは組まれています。
人対人のモードを実装したときは、Program.csで全く問題が起きなかったのですが、
Computer.csを使ってProgram.csのPut関数を使用しようとすると、うまくいきませんでした。
<起きたこと>
Put関数でListの中身を変えたはずなのにListの中身(盤面の状態)が変わっていなかった。
詳しい方、どうかご教授・ご提案の程よろしくお願いいたします。
また、コードがとても汚いと思いますが、その改善点なども教えていただければ幸いです。
コードで不明な点がありましたら教えて頂けたら全てのコードを出します。
達成したいこと
αβ法を使って、簡単なリバーシを打ってくれるプログラムを作りたい。
該当のソースコード
C#
1// Program.cs 2 3// 盤面の数値と色 4// 黒 -> 0 5// 白 -> 1 6// 空 -> 2 7 8using System.Collections.Generic; 9using System.Windows.Forms; 10 11 12namespace Reversi 13{ 14 public class Program 15 { 16 private static List<List<sbyte>> GetVector(sbyte x, sbyte y, List<sbyte> directions) 17 { 18 // Put, CanPutHere 用の出発地点と方向をもとにしてベクトルを生成する 19 20 sbyte nowX = x; 21 sbyte nowY = y; 22 List<List<sbyte>> result = new List<List<sbyte>>(); 23 24 while (nowX >= 0 && nowX < 8 && nowY >= 0 && nowY < 8) 25 { 26 nowX += directions[0]; 27 nowY += directions[1]; 28 29 result.Add(new List<sbyte> { nowX, nowY }); 30 } 31 result.RemoveAt(result.Count - 1); 32 33 return result; 34 } 35 36 37 public static List<List<sbyte>> Put(List<sbyte> xy, List<List<sbyte>> board, sbyte turn) 38 { 39 // 置く 40 41 sbyte x = xy[0]; 42 sbyte y = xy[1]; 43 44 List<List<sbyte>> tmpBoard = board; 45 tmpBoard[y][x] = turn; 46 47 List<List<sbyte>> serchVector = new List<List<sbyte>>(); 48 for (sbyte i = -1; i <= 1; i++) 49 { 50 for (sbyte j = -1; j <= 1; j++) 51 { 52 if (i == 0 && j == 0) { continue; } 53 serchVector.Add(new List<sbyte> { i, j }); 54 } 55 } 56 57 foreach (List<sbyte> s in serchVector) 58 { 59 List<List<sbyte>> temp = GetVector(x, y, s); 60 bool t1 = false; 61 bool isFirst = true; 62 foreach (List<sbyte> tmp in temp) 63 { 64 if (tmpBoard[tmp[1]][tmp[0]] != 1 - turn) 65 { 66 t1 = tmpBoard[tmp[1]][tmp[0]] == turn; 67 break; 68 } 69 70 if (isFirst) { isFirst = false; } 71 } 72 73 if (t1 && !isFirst) 74 { 75 for (sbyte i = 0; i < temp.Count; i++) 76 { 77 if (tmpBoard[temp[i][1]][temp[i][0]] == 1 - turn) 78 { 79 tmpBoard[temp[i][1]][temp[i][0]] = turn; 80 } 81 else { break; } 82 } 83 } 84 } 85 return tmpBoard; 86 } 87 88 89 public static bool CanPutHere(List<sbyte> xy, List<List<sbyte>> board, sbyte turn) 90 { 91 //ここにおけるか 92 93 sbyte x = xy[0]; 94 sbyte y = xy[1]; 95 96 if (board[y][x] != 2) { return false; } 97 98 List<List<sbyte>> serchVector = new List<List<sbyte>>(); 99 for (sbyte i = -1; i <= 1; i++) 100 { 101 for (sbyte j = -1; j <= 1; j++) 102 { 103 if (i == 0 && j == 0) { continue; } 104 serchVector.Add(new List<sbyte> { i, j }); 105 } 106 } 107 108 foreach (List<sbyte> s in serchVector) 109 { 110 List<List<sbyte>> temp = GetVector(x, y, s); 111 bool t1 = false; 112 bool isFirst = true; 113 foreach (List<sbyte> tmp in temp) 114 { 115 if (board[tmp[1]][tmp[0]] != 1 - turn) 116 { 117 t1 = board[tmp[1]][tmp[0]] == turn; 118 break; 119 } 120 121 if (isFirst) { isFirst = false; } 122 } 123 124 if (t1 && !isFirst) { return true; } 125 } 126 return false; 127 } 128 } 129} 130
C#
1// Computer.cs 2 3using System.Collections.Generic; 4using System.Linq; 5using System; 6using System.Windows.Forms; 7 8 9namespace Reversi 10{ 11 public class Computer : Program 12 { 13 // どのくらい深くよむか 14 static readonly sbyte maxDepth = 5; 15 16 public List<sbyte> AlphaBetaMain(List<List<sbyte>> board, sbyte turn) 17 { 18 // 外部から呼び出される関数 19 20 List<List<sbyte>> npList = NextPut(board, turn); 21 22 int alpha = int.MinValue; 23 int beta = int.MaxValue; 24 25 List<sbyte> result = new List<sbyte>(); 26 foreach (List<sbyte> np in npList) 27 { 28 List<List<sbyte>> putBoard = Put(np, board, turn); 29 30 int re = ABMin(putBoard, (sbyte)(1 - turn), alpha, beta, 0, turn); 31 if (alpha <= re) 32 { 33 alpha = re; 34 result = np; 35 } 36 } 37 38 return result; 39 } 40 41 int ABMin(List<List<sbyte>> board, sbyte turn, int alpha, int beta, sbyte depth, sbyte mainTurn) 42 { 43 if (depth >= maxDepth) 44 { 45 return EvaluationValue(board, mainTurn); 46 } 47 48 List<List<sbyte>> npList = NextPut(board, turn); 49 50 foreach (List<sbyte> np in npList) 51 { 52 List<List<sbyte>> putBoard = Put(np, board, turn); 53 int re = ABMax(putBoard, (sbyte)(1 - turn), alpha, beta, (sbyte)(depth + 1), mainTurn); 54 55 if (beta > re) 56 { 57 beta = re; 58 } 59 60 if (alpha >= beta) 61 { 62 return alpha; 63 } 64 } 65 66 return beta; 67 } 68 69 int ABMax(List<List<sbyte>> board, sbyte turn, int alpha, int beta, sbyte depth, sbyte mainTurn) 70 { 71 if (depth >= maxDepth) 72 { 73 return EvaluationValue(board, mainTurn); 74 } 75 76 List<List<sbyte>> npList = NextPut(board, turn); 77 78 foreach (List<sbyte> np in npList) 79 { 80 List<List<sbyte>> putBoard = Put(np, board, turn); 81 int re = ABMin(putBoard, (sbyte)(1 - turn), alpha, beta, (sbyte)(depth + 1), mainTurn); 82 83 if (alpha < re) 84 { 85 alpha = re; 86 87 } 88 if (alpha >= beta) 89 { 90 return beta; 91 } 92 } 93 94 return alpha; 95 } 96 97 static int EvaluationValue(List<List<sbyte>> board, sbyte turn) 98 { 99 // 評価関数 100 // 長くて無関係なので省略 101 } 102 } 103} 104
C#
1// MainWindow.xaml.cs 2 3// Computer.cs の AlphaBetaMain関数の呼び出し元 4// XAMLを使っています。 5 6 7using System; 8using System.Collections.Generic; 9using System.Windows; 10using System.Windows.Input; 11 12 13namespace Reversi 14{ 15 public partial class MainWindow : Window 16 { 17 18 // 設定のための様々な変数 19 static bool isHoldingTheGame = false; 20 static sbyte Mturn = 0; 21 static bool Mhints = false; 22 static List<string> playersNames = new List<string> { "Player1", "Player2", "" }; 23 static List<List<sbyte>> Mboard = Program.MakeNewBoard(); 24 static List<string> Mkifu = new List<string>(); 25 static readonly List<string> MkifuA = new List<string> { "A", "B", "C", "D", "E", "F", "G", "H"}; 26 static readonly string com = "COM"; 27 28 29 30 public MainWindow() 31 { 32 InitializeComponent(); 33 ShowBoard(Mboard); 34 } 35 36 public void ShowBoard(List<List<sbyte>> board) 37 { 38 // 画面に盤面を表示させる関数 39 } 40 41 void PutAndAfter(List<sbyte> xy) 42 { 43 if (xy[0] >= 0 && xy[0] < 8 && xy[1] >= 0 && xy[1] < 8) 44 { 45 if (Program.CanPutHere(xy, Mboard, Mturn)) 46 { 47 Mboard = Program.Put(xy, Mboard, Mturn); // 置く 48 49 // 以下、棋譜とか終了処理、Pass処理等 50 Mkifu.Add(playersNames[Mturn] + " > " + MkifuA[xy[0]].ToString() + xy[1].ToString()); 51 Mturn = (sbyte)(1 - Mturn); 52 ShowBoard(Mboard); 53 54 if (Program.IsFin(Mboard)) 55 { 56 List<sbyte> coSts = Program.CountStorns(Mboard); 57 string txt; 58 if (coSts[0] == coSts[1]) { txt = "引き分け"; } 59 else if (coSts[0] > coSts[1]) { txt = playersNames[0] + "の勝ち"; } 60 else { txt = playersNames[1] + "の勝ち"; } 61 62 MessageBox.Show("ゲーム終了\n" + txt); 63 64 isHoldingTheGame = false; 65 66 Announcement win = new Announcement(coSts, Mkifu, playersNames); 67 win.Show(); 68 69 ShowBoard(Program.MakeNewBoard()); 70 } 71 else if (Program.IsPass(Mboard, Mturn)) 72 { 73 MessageBox.Show(playersNames[Mturn] + "は、どこにも置けません。\nパスです。"); 74 Mkifu.Add(playersNames[Mturn] + " > Pass"); 75 76 Mturn = (sbyte)(1 - Mturn); 77 ShowBoard(Mboard); 78 } 79 } 80 } 81 } 82 83 84 void ComMes() 85 { 86 // 問題の関数の呼び出し元 87 List<List<sbyte>> board = Mboard; 88 Computer Coc = new Computer(); 89 List<sbyte> Nextp = Coc.AlphaBetaMain(board, Mturn); 90 PutAndAfter(Nextp); 91 } 92 93 // その他GUIのイベント関数が沢山 94 } 95} 96
> C#を始めたばかりの超初心者です。
「超初心者」が書いたとはとても思えないコードで、違和感ありあり、何かウラとかがありそうな気がしますけど、気のせいでしょうか?
デバッガを使って怪しいところにブレークポイントを置いてステップ実行し、コードの動きや変数などが期待通りか調べるぐらいのことはしたのでしょうか?
遅れてすみません。
1)前にPythonを少ししていたのでforとかはわかるのですが、staticとかなどは、全然わからないので、公式のページやいろいろな人の解説などを持ってきてなんとか作っています。
2)デバッガ、MessageBoxなど使って1つ1つ調べてもわからなかったというのが今の状態です。
コードを丸投げして他人にデバッグしてもらうのを期待するなら、コピペすれば動いて「Listの中身が変化しない」という問題を再現できる必要最低限(ここが大事。あくまで必要最低限)のごく短いサンプルコードを書いてもらえないと難しいかと。
それを作る段階で原因が分かって自己解決できるかも。そういうケースは多いです。
分かりました
回答1件
あなたの回答
tips
プレビュー