質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.48%
C#

C#はマルチパラダイムプログラミング言語の1つで、命令形・宣言型・関数型・ジェネリック型・コンポーネント指向・オブジェクティブ指向のプログラミング開発すべてに対応しています。

Q&A

解決済

1回答

512閲覧

Listの中身が変化しない

Gfk_L

総合スコア15

C#

C#はマルチパラダイムプログラミング言語の1つで、命令形・宣言型・関数型・ジェネリック型・コンポーネント指向・オブジェクティブ指向のプログラミング開発すべてに対応しています。

0グッド

0クリップ

投稿2022/04/03 06:01

編集2022/04/03 09:24

前提

リバーシのプログラムを作っています。

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

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

退会済みユーザー

退会済みユーザー

2022/04/03 08:25 編集

> C#を始めたばかりの超初心者です。 「超初心者」が書いたとはとても思えないコードで、違和感ありあり、何かウラとかがありそうな気がしますけど、気のせいでしょうか? デバッガを使って怪しいところにブレークポイントを置いてステップ実行し、コードの動きや変数などが期待通りか調べるぐらいのことはしたのでしょうか?
Gfk_L

2022/04/03 08:51

遅れてすみません。 1)前にPythonを少ししていたのでforとかはわかるのですが、staticとかなどは、全然わからないので、公式のページやいろいろな人の解説などを持ってきてなんとか作っています。 2)デバッガ、MessageBoxなど使って1つ1つ調べてもわからなかったというのが今の状態です。
退会済みユーザー

退会済みユーザー

2022/04/03 09:28

コードを丸投げして他人にデバッグしてもらうのを期待するなら、コピペすれば動いて「Listの中身が変化しない」という問題を再現できる必要最低限(ここが大事。あくまで必要最低限)のごく短いサンプルコードを書いてもらえないと難しいかと。 それを作る段階で原因が分かって自己解決できるかも。そういうケースは多いです。
Gfk_L

2022/04/03 09:40

分かりました
guest

回答1

0

自己解決

MainWindow.xaml.cs の Put の tmpBoard の定義を次に変える

C#

1// MainWindow.xaml.cs 2// Put 3 List<List<sbyte>> tmpBoard = new List<List<sbyte>>(); 4 5 foreach (List<sbyte> b in board) 6 { 7 List<sbyte> tmp = new List<sbyte>(); 8 foreach (sbyte c in b) 9 { 10 tmp.Add(c); 11 } 12 tmpBoard.Add(tmp); 13 }

投稿2022/04/04 09:19

Gfk_L

総合スコア15

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.48%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問