").text(i))},100))},menuselect:function(t,e){var i=e.item.data("ui-autocomplete-item"),s=this.previous;this.element[0]!==x.ui.safeActiveElement(this.document[0])&&(this.element.trigger("focus"),this.previous=s,this._delay(function(){this.previous=s,this.selectedItem=i})),!1!==this._trigger("select",t,{item:i})&&this._value(i.value),this.term=this._value(),this.close(t),this.selectedItem=i}}),this.liveRegion=x("
",{role:"status","aria-live":"assertive","aria-relevant":"additions"}).appendTo(this.document[0].body),this._addClass(this.liveRegion,null,"ui-helper-hidden-accessible"),this._on(this.window,{beforeunload:function(){this.element.removeAttr("autocomplete")}})},_destroy:function(){clearTimeout(this.searching),this.element.removeAttr("autocomplete"),this.menu.element.remove(),this.liveRegion.remove()},_setOption:function(t,e){this._super(t,e),"source"===t&&this._initSource(),"appendTo"===t&&this.menu.element.appendTo(this._appendTo()),"disabled"===t&&e&&this.xhr&&this.xhr.abort()},_isEventTargetInWidget:function(t){var e=this.menu.element[0];return t.target===this.element[0]||t.target===e||x.contains(e,t.target)},_closeOnClickOutside:function(t){this._isEventTargetInWidget(t)||this.close()},_appendTo:function(){var t=this.options.appendTo;return t=!(t=!(t=t&&(t.jquery||t.nodeType?x(t):this.document.find(t).eq(0)))||!t[0]?this.element.closest(".ui-front, dialog"):t).length?this.document[0].body:t},_initSource:function(){var i,s,n=this;Array.isArray(this.options.source)?(i=this.options.source,this.source=function(t,e){e(x.ui.autocomplete.filter(i,t.term))}):"string"==typeof this.options.source?(s=this.options.source,this.source=function(t,e){n.xhr&&n.xhr.abort(),n.xhr=x.ajax({url:s,data:t,dataType:"json",success:function(t){e(t)},error:function(){e([])}})}):this.source=this.options.source},_searchTimeout:function(s){clearTimeout(this.searching),this.searching=this._delay(function(){var t=this.term===this._value(),e=this.menu.element.is(":visible"),i=s.altKey||s.ctrlKey||s.metaKey||s.shiftKey;t&&(e||i)||(this.selectedItem=null,this.search(null,s))},this.options.delay)},search:function(t,e){return t=null!=t?t:this._value(),this.term=this._value(),t.length
").append(x("").text(e.label)).appendTo(t)},_move:function(t,e){if(this.menu.element.is(":visible"))return this.menu.isFirstItem()&&/^previous/.test(t)||this.menu.isLastItem()&&/^next/.test(t)?(this.isMultiLine||this._value(this.term),void this.menu.blur()):void this.menu[t](e);this.search(null,e)},widget:function(){return this.menu.element},_value:function(){return this.valueMethod.apply(this.element,arguments)},_keyEvent:function(t,e){this.isMultiLine&&!this.menu.element.is(":visible")||(this._move(t,e),e.preventDefault())},_isContentEditable:function(t){if(!t.length)return!1;var e=t.prop("contentEditable");return"inherit"===e?this._isContentEditable(t.parent()):"true"===e}}),x.extend(x.ui.autocomplete,{escapeRegex:function(t){return t.replace(/[\-\[\]{}()*+?.,\\\^$|#\s]/g,"\\$&")},filter:function(t,e){var i=new RegExp(x.ui.autocomplete.escapeRegex(e),"i");return x.grep(t,function(t){return i.test(t.label||t.value||t)})}}),x.widget("ui.autocomplete",x.ui.autocomplete,{options:{messages:{noResults:"No search results.",results:function(t){return t+(1
").text(e))},100))}});x.ui.autocomplete});
\ No newline at end of file
diff --git a/tictactoe/jdoc/script.js b/tictactoe/jdoc/script.js
new file mode 100644
index 00000000..0765364e
--- /dev/null
+++ b/tictactoe/jdoc/script.js
@@ -0,0 +1,132 @@
+/*
+ * Copyright (c) 2013, 2020, Oracle and/or its affiliates. All rights reserved.
+ * ORACLE PROPRIETARY/CONFIDENTIAL. Use is subject to license terms.
+ *
+ *
+ *
+ *
+ *
+ *
+ *
+ *
+ *
+ *
+ *
+ *
+ *
+ *
+ *
+ *
+ *
+ *
+ *
+ *
+ */
+
+var moduleSearchIndex;
+var packageSearchIndex;
+var typeSearchIndex;
+var memberSearchIndex;
+var tagSearchIndex;
+function loadScripts(doc, tag) {
+ createElem(doc, tag, 'search.js');
+
+ createElem(doc, tag, 'module-search-index.js');
+ createElem(doc, tag, 'package-search-index.js');
+ createElem(doc, tag, 'type-search-index.js');
+ createElem(doc, tag, 'member-search-index.js');
+ createElem(doc, tag, 'tag-search-index.js');
+}
+
+function createElem(doc, tag, path) {
+ var script = doc.createElement(tag);
+ var scriptElement = doc.getElementsByTagName(tag)[0];
+ script.src = pathtoroot + path;
+ scriptElement.parentNode.insertBefore(script, scriptElement);
+}
+
+function show(tableId, selected, columns) {
+ if (tableId !== selected) {
+ document.querySelectorAll('div.' + tableId + ':not(.' + selected + ')')
+ .forEach(function(elem) {
+ elem.style.display = 'none';
+ });
+ }
+ document.querySelectorAll('div.' + selected)
+ .forEach(function(elem, index) {
+ elem.style.display = '';
+ var isEvenRow = index % (columns * 2) < columns;
+ elem.classList.remove(isEvenRow ? oddRowColor : evenRowColor);
+ elem.classList.add(isEvenRow ? evenRowColor : oddRowColor);
+ });
+ updateTabs(tableId, selected);
+}
+
+function updateTabs(tableId, selected) {
+ document.querySelector('div#' + tableId +' .summary-table')
+ .setAttribute('aria-labelledby', selected);
+ document.querySelectorAll('button[id^="' + tableId + '"]')
+ .forEach(function(tab, index) {
+ if (selected === tab.id || (tableId === selected && index === 0)) {
+ tab.className = activeTableTab;
+ tab.setAttribute('aria-selected', true);
+ tab.setAttribute('tabindex',0);
+ } else {
+ tab.className = tableTab;
+ tab.setAttribute('aria-selected', false);
+ tab.setAttribute('tabindex',-1);
+ }
+ });
+}
+
+function switchTab(e) {
+ var selected = document.querySelector('[aria-selected=true]');
+ if (selected) {
+ if ((e.keyCode === 37 || e.keyCode === 38) && selected.previousSibling) {
+ // left or up arrow key pressed: move focus to previous tab
+ selected.previousSibling.click();
+ selected.previousSibling.focus();
+ e.preventDefault();
+ } else if ((e.keyCode === 39 || e.keyCode === 40) && selected.nextSibling) {
+ // right or down arrow key pressed: move focus to next tab
+ selected.nextSibling.click();
+ selected.nextSibling.focus();
+ e.preventDefault();
+ }
+ }
+}
+
+var updateSearchResults = function() {};
+
+function indexFilesLoaded() {
+ return moduleSearchIndex
+ && packageSearchIndex
+ && typeSearchIndex
+ && memberSearchIndex
+ && tagSearchIndex;
+}
+
+// Workaround for scroll position not being included in browser history (8249133)
+document.addEventListener("DOMContentLoaded", function(e) {
+ var contentDiv = document.querySelector("div.flex-content");
+ window.addEventListener("popstate", function(e) {
+ if (e.state !== null) {
+ contentDiv.scrollTop = e.state;
+ }
+ });
+ window.addEventListener("hashchange", function(e) {
+ history.replaceState(contentDiv.scrollTop, document.title);
+ });
+ contentDiv.addEventListener("scroll", function(e) {
+ var timeoutID;
+ if (!timeoutID) {
+ timeoutID = setTimeout(function() {
+ history.replaceState(contentDiv.scrollTop, document.title);
+ timeoutID = null;
+ }, 100);
+ }
+ });
+ if (!location.hash) {
+ history.replaceState(contentDiv.scrollTop, document.title);
+ }
+});
diff --git a/tictactoe/jdoc/search.js b/tictactoe/jdoc/search.js
new file mode 100644
index 00000000..13aba853
--- /dev/null
+++ b/tictactoe/jdoc/search.js
@@ -0,0 +1,354 @@
+/*
+ * Copyright (c) 2015, 2020, Oracle and/or its affiliates. All rights reserved.
+ * ORACLE PROPRIETARY/CONFIDENTIAL. Use is subject to license terms.
+ *
+ *
+ *
+ *
+ *
+ *
+ *
+ *
+ *
+ *
+ *
+ *
+ *
+ *
+ *
+ *
+ *
+ *
+ *
+ *
+ */
+
+var noResult = {l: "No results found"};
+var loading = {l: "Loading search index..."};
+var catModules = "Modules";
+var catPackages = "Packages";
+var catTypes = "Classes and Interfaces";
+var catMembers = "Members";
+var catSearchTags = "Search Tags";
+var highlight = "$& ";
+var searchPattern = "";
+var fallbackPattern = "";
+var RANKING_THRESHOLD = 2;
+var NO_MATCH = 0xffff;
+var MIN_RESULTS = 3;
+var MAX_RESULTS = 500;
+var UNNAMED = "";
+function escapeHtml(str) {
+ return str.replace(//g, ">");
+}
+function getHighlightedText(item, matcher, fallbackMatcher) {
+ var escapedItem = escapeHtml(item);
+ var highlighted = escapedItem.replace(matcher, highlight);
+ if (highlighted === escapedItem) {
+ highlighted = escapedItem.replace(fallbackMatcher, highlight)
+ }
+ return highlighted;
+}
+function getURLPrefix(ui) {
+ var urlPrefix="";
+ var slash = "/";
+ if (ui.item.category === catModules) {
+ return ui.item.l + slash;
+ } else if (ui.item.category === catPackages && ui.item.m) {
+ return ui.item.m + slash;
+ } else if (ui.item.category === catTypes || ui.item.category === catMembers) {
+ if (ui.item.m) {
+ urlPrefix = ui.item.m + slash;
+ } else {
+ $.each(packageSearchIndex, function(index, item) {
+ if (item.m && ui.item.p === item.l) {
+ urlPrefix = item.m + slash;
+ }
+ });
+ }
+ }
+ return urlPrefix;
+}
+function createSearchPattern(term) {
+ var pattern = "";
+ var isWordToken = false;
+ term.replace(/,\s*/g, ", ").trim().split(/\s+/).forEach(function(w, index) {
+ if (index > 0) {
+ // whitespace between identifiers is significant
+ pattern += (isWordToken && /^\w/.test(w)) ? "\\s+" : "\\s*";
+ }
+ var tokens = w.split(/(?=[A-Z,.()<>[\/])/);
+ for (var i = 0; i < tokens.length; i++) {
+ var s = tokens[i];
+ if (s === "") {
+ continue;
+ }
+ pattern += $.ui.autocomplete.escapeRegex(s);
+ isWordToken = /\w$/.test(s);
+ if (isWordToken) {
+ pattern += "([a-z0-9_$<>\\[\\]]*?)";
+ }
+ }
+ });
+ return pattern;
+}
+function createMatcher(pattern, flags) {
+ var isCamelCase = /[A-Z]/.test(pattern);
+ return new RegExp(pattern, flags + (isCamelCase ? "" : "i"));
+}
+var watermark = 'Search';
+$(function() {
+ var search = $("#search-input");
+ var reset = $("#reset-button");
+ search.val('');
+ search.prop("disabled", false);
+ reset.prop("disabled", false);
+ search.val(watermark).addClass('watermark');
+ search.blur(function() {
+ if ($(this).val().length === 0) {
+ $(this).val(watermark).addClass('watermark');
+ }
+ });
+ search.on('click keydown paste', function() {
+ if ($(this).val() === watermark) {
+ $(this).val('').removeClass('watermark');
+ }
+ });
+ reset.click(function() {
+ search.val('').focus();
+ });
+ search.focus()[0].setSelectionRange(0, 0);
+});
+$.widget("custom.catcomplete", $.ui.autocomplete, {
+ _create: function() {
+ this._super();
+ this.widget().menu("option", "items", "> :not(.ui-autocomplete-category)");
+ },
+ _renderMenu: function(ul, items) {
+ var rMenu = this;
+ var currentCategory = "";
+ rMenu.menu.bindings = $();
+ $.each(items, function(index, item) {
+ var li;
+ if (item.category && item.category !== currentCategory) {
+ ul.append("" + item.category + " ");
+ currentCategory = item.category;
+ }
+ li = rMenu._renderItemData(ul, item);
+ if (item.category) {
+ li.attr("aria-label", item.category + " : " + item.l);
+ li.attr("class", "result-item");
+ } else {
+ li.attr("aria-label", item.l);
+ li.attr("class", "result-item");
+ }
+ });
+ },
+ _renderItem: function(ul, item) {
+ var label = "";
+ var matcher = createMatcher(escapeHtml(searchPattern), "g");
+ var fallbackMatcher = new RegExp(fallbackPattern, "gi")
+ if (item.category === catModules) {
+ label = getHighlightedText(item.l, matcher, fallbackMatcher);
+ } else if (item.category === catPackages) {
+ label = getHighlightedText(item.l, matcher, fallbackMatcher);
+ } else if (item.category === catTypes) {
+ label = (item.p && item.p !== UNNAMED)
+ ? getHighlightedText(item.p + "." + item.l, matcher, fallbackMatcher)
+ : getHighlightedText(item.l, matcher, fallbackMatcher);
+ } else if (item.category === catMembers) {
+ label = (item.p && item.p !== UNNAMED)
+ ? getHighlightedText(item.p + "." + item.c + "." + item.l, matcher, fallbackMatcher)
+ : getHighlightedText(item.c + "." + item.l, matcher, fallbackMatcher);
+ } else if (item.category === catSearchTags) {
+ label = getHighlightedText(item.l, matcher, fallbackMatcher);
+ } else {
+ label = item.l;
+ }
+ var li = $(" ").appendTo(ul);
+ var div = $("
").appendTo(li);
+ if (item.category === catSearchTags && item.h) {
+ if (item.d) {
+ div.html(label + " (" + item.h + ") "
+ + item.d + " ");
+ } else {
+ div.html(label + " (" + item.h + ") ");
+ }
+ } else {
+ if (item.m) {
+ div.html(item.m + "/" + label);
+ } else {
+ div.html(label);
+ }
+ }
+ return li;
+ }
+});
+function rankMatch(match, category) {
+ if (!match) {
+ return NO_MATCH;
+ }
+ var index = match.index;
+ var input = match.input;
+ var leftBoundaryMatch = 2;
+ var periferalMatch = 0;
+ // make sure match is anchored on a left word boundary
+ if (index === 0 || /\W/.test(input[index - 1]) || "_" === input[index]) {
+ leftBoundaryMatch = 0;
+ } else if ("_" === input[index - 1] || (input[index] === input[index].toUpperCase() && !/^[A-Z0-9_$]+$/.test(input))) {
+ leftBoundaryMatch = 1;
+ }
+ var matchEnd = index + match[0].length;
+ var leftParen = input.indexOf("(");
+ var endOfName = leftParen > -1 ? leftParen : input.length;
+ // exclude peripheral matches
+ if (category !== catModules && category !== catSearchTags) {
+ var delim = category === catPackages ? "/" : ".";
+ if (leftParen > -1 && leftParen < index) {
+ periferalMatch += 2;
+ } else if (input.lastIndexOf(delim, endOfName) >= matchEnd) {
+ periferalMatch += 2;
+ }
+ }
+ var delta = match[0].length === endOfName ? 0 : 1; // rank full match higher than partial match
+ for (var i = 1; i < match.length; i++) {
+ // lower ranking if parts of the name are missing
+ if (match[i])
+ delta += match[i].length;
+ }
+ if (category === catTypes) {
+ // lower ranking if a type name contains unmatched camel-case parts
+ if (/[A-Z]/.test(input.substring(matchEnd)))
+ delta += 5;
+ if (/[A-Z]/.test(input.substring(0, index)))
+ delta += 5;
+ }
+ return leftBoundaryMatch + periferalMatch + (delta / 200);
+
+}
+function doSearch(request, response) {
+ var result = [];
+ searchPattern = createSearchPattern(request.term);
+ fallbackPattern = createSearchPattern(request.term.toLowerCase());
+ if (searchPattern === "") {
+ return this.close();
+ }
+ var camelCaseMatcher = createMatcher(searchPattern, "");
+ var fallbackMatcher = new RegExp(fallbackPattern, "i");
+
+ function searchIndexWithMatcher(indexArray, matcher, category, nameFunc) {
+ if (indexArray) {
+ var newResults = [];
+ $.each(indexArray, function (i, item) {
+ item.category = category;
+ var ranking = rankMatch(matcher.exec(nameFunc(item)), category);
+ if (ranking < RANKING_THRESHOLD) {
+ newResults.push({ranking: ranking, item: item});
+ }
+ return newResults.length <= MAX_RESULTS;
+ });
+ return newResults.sort(function(e1, e2) {
+ return e1.ranking - e2.ranking;
+ }).map(function(e) {
+ return e.item;
+ });
+ }
+ return [];
+ }
+ function searchIndex(indexArray, category, nameFunc) {
+ var primaryResults = searchIndexWithMatcher(indexArray, camelCaseMatcher, category, nameFunc);
+ result = result.concat(primaryResults);
+ if (primaryResults.length <= MIN_RESULTS && !camelCaseMatcher.ignoreCase) {
+ var secondaryResults = searchIndexWithMatcher(indexArray, fallbackMatcher, category, nameFunc);
+ result = result.concat(secondaryResults.filter(function (item) {
+ return primaryResults.indexOf(item) === -1;
+ }));
+ }
+ }
+
+ searchIndex(moduleSearchIndex, catModules, function(item) { return item.l; });
+ searchIndex(packageSearchIndex, catPackages, function(item) {
+ return (item.m && request.term.indexOf("/") > -1)
+ ? (item.m + "/" + item.l) : item.l;
+ });
+ searchIndex(typeSearchIndex, catTypes, function(item) {
+ return request.term.indexOf(".") > -1 ? item.p + "." + item.l : item.l;
+ });
+ searchIndex(memberSearchIndex, catMembers, function(item) {
+ return request.term.indexOf(".") > -1
+ ? item.p + "." + item.c + "." + item.l : item.l;
+ });
+ searchIndex(tagSearchIndex, catSearchTags, function(item) { return item.l; });
+
+ if (!indexFilesLoaded()) {
+ updateSearchResults = function() {
+ doSearch(request, response);
+ }
+ result.unshift(loading);
+ } else {
+ updateSearchResults = function() {};
+ }
+ response(result);
+}
+$(function() {
+ $("#search-input").catcomplete({
+ minLength: 1,
+ delay: 300,
+ source: doSearch,
+ response: function(event, ui) {
+ if (!ui.content.length) {
+ ui.content.push(noResult);
+ } else {
+ $("#search-input").empty();
+ }
+ },
+ autoFocus: true,
+ focus: function(event, ui) {
+ return false;
+ },
+ position: {
+ collision: "flip"
+ },
+ select: function(event, ui) {
+ if (ui.item.category) {
+ var url = getURLPrefix(ui);
+ if (ui.item.category === catModules) {
+ url += "module-summary.html";
+ } else if (ui.item.category === catPackages) {
+ if (ui.item.u) {
+ url = ui.item.u;
+ } else {
+ url += ui.item.l.replace(/\./g, '/') + "/package-summary.html";
+ }
+ } else if (ui.item.category === catTypes) {
+ if (ui.item.u) {
+ url = ui.item.u;
+ } else if (ui.item.p === UNNAMED) {
+ url += ui.item.l + ".html";
+ } else {
+ url += ui.item.p.replace(/\./g, '/') + "/" + ui.item.l + ".html";
+ }
+ } else if (ui.item.category === catMembers) {
+ if (ui.item.p === UNNAMED) {
+ url += ui.item.c + ".html" + "#";
+ } else {
+ url += ui.item.p.replace(/\./g, '/') + "/" + ui.item.c + ".html" + "#";
+ }
+ if (ui.item.u) {
+ url += ui.item.u;
+ } else {
+ url += ui.item.l;
+ }
+ } else if (ui.item.category === catSearchTags) {
+ url += ui.item.u;
+ }
+ if (top !== window) {
+ parent.classFrame.location = pathtoroot + url;
+ } else {
+ window.location.href = pathtoroot + url;
+ }
+ $("#search-input").focus();
+ }
+ }
+ });
+});
diff --git a/tictactoe/jdoc/stylesheet.css b/tictactoe/jdoc/stylesheet.css
new file mode 100644
index 00000000..6dc5b365
--- /dev/null
+++ b/tictactoe/jdoc/stylesheet.css
@@ -0,0 +1,866 @@
+/*
+ * Javadoc style sheet
+ */
+
+@import url('resources/fonts/dejavu.css');
+
+/*
+ * Styles for individual HTML elements.
+ *
+ * These are styles that are specific to individual HTML elements. Changing them affects the style of a particular
+ * HTML element throughout the page.
+ */
+
+body {
+ background-color:#ffffff;
+ color:#353833;
+ font-family:'DejaVu Sans', Arial, Helvetica, sans-serif;
+ font-size:14px;
+ margin:0;
+ padding:0;
+ height:100%;
+ width:100%;
+}
+iframe {
+ margin:0;
+ padding:0;
+ height:100%;
+ width:100%;
+ overflow-y:scroll;
+ border:none;
+}
+a:link, a:visited {
+ text-decoration:none;
+ color:#4A6782;
+}
+a[href]:hover, a[href]:focus {
+ text-decoration:none;
+ color:#bb7a2a;
+}
+a[name] {
+ color:#353833;
+}
+pre {
+ font-family:'DejaVu Sans Mono', monospace;
+ font-size:14px;
+}
+h1 {
+ font-size:20px;
+}
+h2 {
+ font-size:18px;
+}
+h3 {
+ font-size:16px;
+}
+h4 {
+ font-size:15px;
+}
+h5 {
+ font-size:14px;
+}
+h6 {
+ font-size:13px;
+}
+ul {
+ list-style-type:disc;
+}
+code, tt {
+ font-family:'DejaVu Sans Mono', monospace;
+}
+:not(h1, h2, h3, h4, h5, h6) > code,
+:not(h1, h2, h3, h4, h5, h6) > tt {
+ font-size:14px;
+ padding-top:4px;
+ margin-top:8px;
+ line-height:1.4em;
+}
+dt code {
+ font-family:'DejaVu Sans Mono', monospace;
+ font-size:14px;
+ padding-top:4px;
+}
+.summary-table dt code {
+ font-family:'DejaVu Sans Mono', monospace;
+ font-size:14px;
+ vertical-align:top;
+ padding-top:4px;
+}
+sup {
+ font-size:8px;
+}
+button {
+ font-family: 'DejaVu Sans', Arial, Helvetica, sans-serif;
+ font-size: 14px;
+}
+/*
+ * Styles for HTML generated by javadoc.
+ *
+ * These are style classes that are used by the standard doclet to generate HTML documentation.
+ */
+
+/*
+ * Styles for document title and copyright.
+ */
+.clear {
+ clear:both;
+ height:0;
+ overflow:hidden;
+}
+.about-language {
+ float:right;
+ padding:0 21px 8px 8px;
+ font-size:11px;
+ margin-top:-9px;
+ height:2.9em;
+}
+.legal-copy {
+ margin-left:.5em;
+}
+.tab {
+ background-color:#0066FF;
+ color:#ffffff;
+ padding:8px;
+ width:5em;
+ font-weight:bold;
+}
+/*
+ * Styles for navigation bar.
+ */
+@media screen {
+ .flex-box {
+ position:fixed;
+ display:flex;
+ flex-direction:column;
+ height: 100%;
+ width: 100%;
+ }
+ .flex-header {
+ flex: 0 0 auto;
+ }
+ .flex-content {
+ flex: 1 1 auto;
+ overflow-y: auto;
+ }
+}
+.top-nav {
+ background-color:#4D7A97;
+ color:#FFFFFF;
+ float:left;
+ padding:0;
+ width:100%;
+ clear:right;
+ min-height:2.8em;
+ padding-top:10px;
+ overflow:hidden;
+ font-size:12px;
+}
+.sub-nav {
+ background-color:#dee3e9;
+ float:left;
+ width:100%;
+ overflow:hidden;
+ font-size:12px;
+}
+.sub-nav div {
+ clear:left;
+ float:left;
+ padding:0 0 5px 6px;
+ text-transform:uppercase;
+}
+.sub-nav .nav-list {
+ padding-top:5px;
+}
+ul.nav-list {
+ display:block;
+ margin:0 25px 0 0;
+ padding:0;
+}
+ul.sub-nav-list {
+ float:left;
+ margin:0 25px 0 0;
+ padding:0;
+}
+ul.nav-list li {
+ list-style:none;
+ float:left;
+ padding: 5px 6px;
+ text-transform:uppercase;
+}
+.sub-nav .nav-list-search {
+ float:right;
+ margin:0 0 0 0;
+ padding:5px 6px;
+ clear:none;
+}
+.nav-list-search label {
+ position:relative;
+ right:-16px;
+}
+ul.sub-nav-list li {
+ list-style:none;
+ float:left;
+ padding-top:10px;
+}
+.top-nav a:link, .top-nav a:active, .top-nav a:visited {
+ color:#FFFFFF;
+ text-decoration:none;
+ text-transform:uppercase;
+}
+.top-nav a:hover {
+ text-decoration:none;
+ color:#bb7a2a;
+ text-transform:uppercase;
+}
+.nav-bar-cell1-rev {
+ background-color:#F8981D;
+ color:#253441;
+ margin: auto 5px;
+}
+.skip-nav {
+ position:absolute;
+ top:auto;
+ left:-9999px;
+ overflow:hidden;
+}
+/*
+ * Hide navigation links and search box in print layout
+ */
+@media print {
+ ul.nav-list, div.sub-nav {
+ display:none;
+ }
+}
+/*
+ * Styles for page header and footer.
+ */
+.title {
+ color:#2c4557;
+ margin:10px 0;
+}
+.sub-title {
+ margin:5px 0 0 0;
+}
+.header ul {
+ margin:0 0 15px 0;
+ padding:0;
+}
+.header ul li, .footer ul li {
+ list-style:none;
+ font-size:13px;
+}
+/*
+ * Styles for headings.
+ */
+body.class-declaration-page .summary h2,
+body.class-declaration-page .details h2,
+body.class-use-page h2,
+body.module-declaration-page .block-list h2 {
+ font-style: italic;
+ padding:0;
+ margin:15px 0;
+}
+body.class-declaration-page .summary h3,
+body.class-declaration-page .details h3,
+body.class-declaration-page .summary .inherited-list h2 {
+ background-color:#dee3e9;
+ border:1px solid #d0d9e0;
+ margin:0 0 6px -8px;
+ padding:7px 5px;
+}
+/*
+ * Styles for page layout containers.
+ */
+main {
+ clear:both;
+ padding:10px 20px;
+ position:relative;
+}
+dl.notes > dt {
+ font-family: 'DejaVu Sans', Arial, Helvetica, sans-serif;
+ font-size:12px;
+ font-weight:bold;
+ margin:10px 0 0 0;
+ color:#4E4E4E;
+}
+dl.notes > dd {
+ margin:5px 10px 10px 0;
+ font-size:14px;
+ font-family:'DejaVu Serif', Georgia, "Times New Roman", Times, serif;
+}
+dl.name-value > dt {
+ margin-left:1px;
+ font-size:1.1em;
+ display:inline;
+ font-weight:bold;
+}
+dl.name-value > dd {
+ margin:0 0 0 1px;
+ font-size:1.1em;
+ display:inline;
+}
+/*
+ * Styles for lists.
+ */
+li.circle {
+ list-style:circle;
+}
+ul.horizontal li {
+ display:inline;
+ font-size:0.9em;
+}
+div.inheritance {
+ margin:0;
+ padding:0;
+}
+div.inheritance div.inheritance {
+ margin-left:2em;
+}
+ul.block-list,
+ul.details-list,
+ul.member-list,
+ul.summary-list {
+ margin:10px 0 10px 0;
+ padding:0;
+}
+ul.block-list > li,
+ul.details-list > li,
+ul.member-list > li,
+ul.summary-list > li {
+ list-style:none;
+ margin-bottom:15px;
+ line-height:1.4;
+}
+.summary-table dl, .summary-table dl dt, .summary-table dl dd {
+ margin-top:0;
+ margin-bottom:1px;
+}
+ul.see-list, ul.see-list-long {
+ padding-left: 0;
+ list-style: none;
+}
+ul.see-list li {
+ display: inline;
+}
+ul.see-list li:not(:last-child):after,
+ul.see-list-long li:not(:last-child):after {
+ content: ", ";
+ white-space: pre-wrap;
+}
+/*
+ * Styles for tables.
+ */
+.summary-table, .details-table {
+ width:100%;
+ border-spacing:0;
+ border-left:1px solid #EEE;
+ border-right:1px solid #EEE;
+ border-bottom:1px solid #EEE;
+ padding:0;
+}
+.caption {
+ position:relative;
+ text-align:left;
+ background-repeat:no-repeat;
+ color:#253441;
+ font-weight:bold;
+ clear:none;
+ overflow:hidden;
+ padding:0;
+ padding-top:10px;
+ padding-left:1px;
+ margin:0;
+ white-space:pre;
+}
+.caption a:link, .caption a:visited {
+ color:#1f389c;
+}
+.caption a:hover,
+.caption a:active {
+ color:#FFFFFF;
+}
+.caption span {
+ white-space:nowrap;
+ padding-top:5px;
+ padding-left:12px;
+ padding-right:12px;
+ padding-bottom:7px;
+ display:inline-block;
+ float:left;
+ background-color:#F8981D;
+ border: none;
+ height:16px;
+}
+div.table-tabs {
+ padding:10px 0 0 1px;
+ margin:0;
+}
+div.table-tabs > button {
+ border: none;
+ cursor: pointer;
+ padding: 5px 12px 7px 12px;
+ font-weight: bold;
+ margin-right: 3px;
+}
+div.table-tabs > button.active-table-tab {
+ background: #F8981D;
+ color: #253441;
+}
+div.table-tabs > button.table-tab {
+ background: #4D7A97;
+ color: #FFFFFF;
+}
+.two-column-summary {
+ display: grid;
+ grid-template-columns: minmax(15%, max-content) minmax(15%, auto);
+}
+.three-column-summary {
+ display: grid;
+ grid-template-columns: minmax(10%, max-content) minmax(15%, max-content) minmax(15%, auto);
+}
+.four-column-summary {
+ display: grid;
+ grid-template-columns: minmax(10%, max-content) minmax(10%, max-content) minmax(10%, max-content) minmax(10%, auto);
+}
+@media screen and (max-width: 600px) {
+ .two-column-summary {
+ display: grid;
+ grid-template-columns: 1fr;
+ }
+}
+@media screen and (max-width: 800px) {
+ .three-column-summary {
+ display: grid;
+ grid-template-columns: minmax(10%, max-content) minmax(25%, auto);
+ }
+ .three-column-summary .col-last {
+ grid-column-end: span 2;
+ }
+}
+@media screen and (max-width: 1000px) {
+ .four-column-summary {
+ display: grid;
+ grid-template-columns: minmax(15%, max-content) minmax(15%, auto);
+ }
+}
+.summary-table > div, .details-table > div {
+ text-align:left;
+ padding: 8px 3px 3px 7px;
+}
+.col-first, .col-second, .col-last, .col-constructor-name, .col-summary-item-name {
+ vertical-align:top;
+ padding-right:0;
+ padding-top:8px;
+ padding-bottom:3px;
+}
+.table-header {
+ background:#dee3e9;
+ font-weight: bold;
+}
+.col-first, .col-first {
+ font-size:13px;
+}
+.col-second, .col-second, .col-last, .col-constructor-name, .col-summary-item-name, .col-last {
+ font-size:13px;
+}
+.col-first, .col-second, .col-constructor-name {
+ vertical-align:top;
+ overflow: auto;
+}
+.col-last {
+ white-space:normal;
+}
+.col-first a:link, .col-first a:visited,
+.col-second a:link, .col-second a:visited,
+.col-first a:link, .col-first a:visited,
+.col-second a:link, .col-second a:visited,
+.col-constructor-name a:link, .col-constructor-name a:visited,
+.col-summary-item-name a:link, .col-summary-item-name a:visited,
+.constant-values-container a:link, .constant-values-container a:visited,
+.all-classes-container a:link, .all-classes-container a:visited,
+.all-packages-container a:link, .all-packages-container a:visited {
+ font-weight:bold;
+}
+.table-sub-heading-color {
+ background-color:#EEEEFF;
+}
+.even-row-color, .even-row-color .table-header {
+ background-color:#FFFFFF;
+}
+.odd-row-color, .odd-row-color .table-header {
+ background-color:#EEEEEF;
+}
+/*
+ * Styles for contents.
+ */
+.deprecated-content {
+ margin:0;
+ padding:10px 0;
+}
+div.block {
+ font-size:14px;
+ font-family:'DejaVu Serif', Georgia, "Times New Roman", Times, serif;
+}
+.col-last div {
+ padding-top:0;
+}
+.col-last a {
+ padding-bottom:3px;
+}
+.module-signature,
+.package-signature,
+.type-signature,
+.member-signature {
+ font-family:'DejaVu Sans Mono', monospace;
+ font-size:14px;
+ margin:14px 0;
+ white-space: pre-wrap;
+}
+.module-signature,
+.package-signature,
+.type-signature {
+ margin-top: 0;
+}
+.member-signature .type-parameters-long,
+.member-signature .parameters,
+.member-signature .exceptions {
+ display: inline-block;
+ vertical-align: top;
+ white-space: pre;
+}
+.member-signature .type-parameters {
+ white-space: normal;
+}
+/*
+ * Styles for formatting effect.
+ */
+.source-line-no {
+ color:green;
+ padding:0 30px 0 0;
+}
+h1.hidden {
+ visibility:hidden;
+ overflow:hidden;
+ font-size:10px;
+}
+.block {
+ display:block;
+ margin:0 10px 5px 0;
+ color:#474747;
+}
+.deprecated-label, .descfrm-type-label, .implementation-label, .member-name-label, .member-name-link,
+.module-label-in-package, .module-label-in-type, .override-specify-label, .package-label-in-type,
+.package-hierarchy-label, .type-name-label, .type-name-link, .search-tag-link, .preview-label {
+ font-weight:bold;
+}
+.deprecation-comment, .help-footnote, .preview-comment {
+ font-style:italic;
+}
+.deprecation-block {
+ font-size:14px;
+ font-family:'DejaVu Serif', Georgia, "Times New Roman", Times, serif;
+ border-style:solid;
+ border-width:thin;
+ border-radius:10px;
+ padding:10px;
+ margin-bottom:10px;
+ margin-right:10px;
+ display:inline-block;
+}
+.preview-block {
+ font-size:14px;
+ font-family:'DejaVu Serif', Georgia, "Times New Roman", Times, serif;
+ border-style:solid;
+ border-width:thin;
+ border-radius:10px;
+ padding:10px;
+ margin-bottom:10px;
+ margin-right:10px;
+ display:inline-block;
+}
+div.block div.deprecation-comment {
+ font-style:normal;
+}
+/*
+ * Styles specific to HTML5 elements.
+ */
+main, nav, header, footer, section {
+ display:block;
+}
+/*
+ * Styles for javadoc search.
+ */
+.ui-autocomplete-category {
+ font-weight:bold;
+ font-size:15px;
+ padding:7px 0 7px 3px;
+ background-color:#4D7A97;
+ color:#FFFFFF;
+}
+.ui-autocomplete {
+ max-height:85%;
+ max-width:65%;
+ overflow-y:scroll;
+ overflow-x:scroll;
+ white-space:nowrap;
+ box-shadow: 0 3px 6px rgba(0,0,0,0.16), 0 3px 6px rgba(0,0,0,0.23);
+}
+ul.ui-autocomplete {
+ position:fixed;
+ z-index:999999;
+ background-color: #FFFFFF;
+}
+ul.ui-autocomplete li {
+ float:left;
+ clear:both;
+ width:100%;
+}
+.ui-autocomplete .result-item {
+ font-size: inherit;
+}
+.ui-autocomplete .result-highlight {
+ font-weight:bold;
+}
+#search-input {
+ background-image:url('resources/glass.png');
+ background-size:13px;
+ background-repeat:no-repeat;
+ background-position:2px 3px;
+ padding-left:20px;
+ position:relative;
+ right:-18px;
+ width:400px;
+}
+#reset-button {
+ background-color: rgb(255,255,255);
+ background-image:url('resources/x.png');
+ background-position:center;
+ background-repeat:no-repeat;
+ background-size:12px;
+ border:0 none;
+ width:16px;
+ height:16px;
+ position:relative;
+ left:-4px;
+ top:-4px;
+ font-size:0px;
+}
+.watermark {
+ color:#545454;
+}
+.search-tag-desc-result {
+ font-style:italic;
+ font-size:11px;
+}
+.search-tag-holder-result {
+ font-style:italic;
+ font-size:12px;
+}
+.search-tag-result:target {
+ background-color:yellow;
+}
+.module-graph span {
+ display:none;
+ position:absolute;
+}
+.module-graph:hover span {
+ display:block;
+ margin: -100px 0 0 100px;
+ z-index: 1;
+}
+.inherited-list {
+ margin: 10px 0 10px 0;
+}
+section.class-description {
+ line-height: 1.4;
+}
+.summary section[class$="-summary"], .details section[class$="-details"],
+.class-uses .detail, .serialized-class-details {
+ padding: 0px 20px 5px 10px;
+ border: 1px solid #ededed;
+ background-color: #f8f8f8;
+}
+.inherited-list, section[class$="-details"] .detail {
+ padding:0 0 5px 8px;
+ background-color:#ffffff;
+ border:none;
+}
+.vertical-separator {
+ padding: 0 5px;
+}
+ul.help-section-list {
+ margin: 0;
+}
+ul.help-subtoc > li {
+ display: inline-block;
+ padding-right: 5px;
+ font-size: smaller;
+}
+ul.help-subtoc > li::before {
+ content: "\2022" ;
+ padding-right:2px;
+}
+span.help-note {
+ font-style: italic;
+}
+/*
+ * Indicator icon for external links.
+ */
+main a[href*="://"]::after {
+ content:"";
+ display:inline-block;
+ background-image:url('data:image/svg+xml; utf8, \
+ \
+ \
+ ');
+ background-size:100% 100%;
+ width:7px;
+ height:7px;
+ margin-left:2px;
+ margin-bottom:4px;
+}
+main a[href*="://"]:hover::after,
+main a[href*="://"]:focus::after {
+ background-image:url('data:image/svg+xml; utf8, \
+ \
+ \
+ ');
+}
+
+/*
+ * Styles for user-provided tables.
+ *
+ * borderless:
+ * No borders, vertical margins, styled caption.
+ * This style is provided for use with existing doc comments.
+ * In general, borderless tables should not be used for layout purposes.
+ *
+ * plain:
+ * Plain borders around table and cells, vertical margins, styled caption.
+ * Best for small tables or for complex tables for tables with cells that span
+ * rows and columns, when the "striped" style does not work well.
+ *
+ * striped:
+ * Borders around the table and vertical borders between cells, striped rows,
+ * vertical margins, styled caption.
+ * Best for tables that have a header row, and a body containing a series of simple rows.
+ */
+
+table.borderless,
+table.plain,
+table.striped {
+ margin-top: 10px;
+ margin-bottom: 10px;
+}
+table.borderless > caption,
+table.plain > caption,
+table.striped > caption {
+ font-weight: bold;
+ font-size: smaller;
+}
+table.borderless th, table.borderless td,
+table.plain th, table.plain td,
+table.striped th, table.striped td {
+ padding: 2px 5px;
+}
+table.borderless,
+table.borderless > thead > tr > th, table.borderless > tbody > tr > th, table.borderless > tr > th,
+table.borderless > thead > tr > td, table.borderless > tbody > tr > td, table.borderless > tr > td {
+ border: none;
+}
+table.borderless > thead > tr, table.borderless > tbody > tr, table.borderless > tr {
+ background-color: transparent;
+}
+table.plain {
+ border-collapse: collapse;
+ border: 1px solid black;
+}
+table.plain > thead > tr, table.plain > tbody tr, table.plain > tr {
+ background-color: transparent;
+}
+table.plain > thead > tr > th, table.plain > tbody > tr > th, table.plain > tr > th,
+table.plain > thead > tr > td, table.plain > tbody > tr > td, table.plain > tr > td {
+ border: 1px solid black;
+}
+table.striped {
+ border-collapse: collapse;
+ border: 1px solid black;
+}
+table.striped > thead {
+ background-color: #E3E3E3;
+}
+table.striped > thead > tr > th, table.striped > thead > tr > td {
+ border: 1px solid black;
+}
+table.striped > tbody > tr:nth-child(even) {
+ background-color: #EEE
+}
+table.striped > tbody > tr:nth-child(odd) {
+ background-color: #FFF
+}
+table.striped > tbody > tr > th, table.striped > tbody > tr > td {
+ border-left: 1px solid black;
+ border-right: 1px solid black;
+}
+table.striped > tbody > tr > th {
+ font-weight: normal;
+}
+/**
+ * Tweak font sizes and paddings for small screens.
+ */
+@media screen and (max-width: 1050px) {
+ #search-input {
+ width: 300px;
+ }
+}
+@media screen and (max-width: 800px) {
+ #search-input {
+ width: 200px;
+ }
+ .top-nav,
+ .bottom-nav {
+ font-size: 11px;
+ padding-top: 6px;
+ }
+ .sub-nav {
+ font-size: 11px;
+ }
+ .about-language {
+ padding-right: 16px;
+ }
+ ul.nav-list li,
+ .sub-nav .nav-list-search {
+ padding: 6px;
+ }
+ ul.sub-nav-list li {
+ padding-top: 5px;
+ }
+ main {
+ padding: 10px;
+ }
+ .summary section[class$="-summary"], .details section[class$="-details"],
+ .class-uses .detail, .serialized-class-details {
+ padding: 0 8px 5px 8px;
+ }
+ body {
+ -webkit-text-size-adjust: none;
+ }
+}
+@media screen and (max-width: 500px) {
+ #search-input {
+ width: 150px;
+ }
+ .top-nav,
+ .bottom-nav {
+ font-size: 10px;
+ }
+ .sub-nav {
+ font-size: 10px;
+ }
+ .about-language {
+ font-size: 10px;
+ padding-right: 12px;
+ }
+}
diff --git a/tictactoe/jdoc/tag-search-index.js b/tictactoe/jdoc/tag-search-index.js
new file mode 100644
index 00000000..9f5ca6e5
--- /dev/null
+++ b/tictactoe/jdoc/tag-search-index.js
@@ -0,0 +1 @@
+tagSearchIndex = [{"l":"常量字段值","h":"","u":"constant-values.html"}];updateSearchResults();
\ No newline at end of file
diff --git a/tictactoe/jdoc/type-search-index.js b/tictactoe/jdoc/type-search-index.js
new file mode 100644
index 00000000..1ab98559
--- /dev/null
+++ b/tictactoe/jdoc/type-search-index.js
@@ -0,0 +1 @@
+typeSearchIndex = [{"l":"All Classes and Interfaces","u":"allclasses-index.html"},{"p":"view","l":"BlockIndex"},{"p":"view","l":"GameBoardView"},{"p":"view","l":"GameStatusView"},{"p":"model","l":"RowGameModel.Move"},{"p":"model","l":"Player"},{"p":"model","l":"RowBlockModel"},{"p":"","l":"RowGameApp"},{"p":"controller","l":"RowGameController"},{"p":"view","l":"RowGameGUI"},{"p":"model","l":"RowGameModel"},{"p":"view","l":"View"}];updateSearchResults();
\ No newline at end of file
diff --git a/tictactoe/jdoc/view/BlockIndex.html b/tictactoe/jdoc/view/BlockIndex.html
new file mode 100644
index 00000000..f459d2d8
--- /dev/null
+++ b/tictactoe/jdoc/view/BlockIndex.html
@@ -0,0 +1,219 @@
+
+
+
+
+BlockIndex (CS520 - Homework 1)
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+您的浏览器已禁用 JavaScript。
+
+
+
+
+
+
+
+
+
+
+public class BlockIndex
+
extends Object
+
+
+
+
+
+
+字段概要
+字段
+
+
+
+
+
private final int
+
+
+
private final int
+
+
+
+
+
+
+
+
+
+
+
+
+方法概要
+
+
所有方法 实例方法 具体方法
+
+
+
+
+
+
int
+
+
+
int
+
+
+
boolean
+
+
+
+
+
+
+
从类继承的方法 java.lang.Object
+
clone , equals , finalize , getClass , hashCode , notify , notifyAll , toString , wait , wait , wait
+
+
+
+
+
+
+
+
+
+字段详细资料
+
+
+
+row
+private final int row
+
+
+
+
+column
+private final int column
+
+
+
+
+
+
+
+
+构造器详细资料
+
+
+
+BlockIndex
+public BlockIndex (int row,
+ int column)
+
+
+
+
+
+
+
+
+方法详细资料
+
+
+
+getRow
+public int getRow ()
+
+
+
+
+getColumn
+public int getColumn ()
+
+
+
+
+matches
+public boolean matches (int row,
+ int column)
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/tictactoe/jdoc/view/GameBoardView.html b/tictactoe/jdoc/view/GameBoardView.html
new file mode 100644
index 00000000..c4b496fd
--- /dev/null
+++ b/tictactoe/jdoc/view/GameBoardView.html
@@ -0,0 +1,248 @@
+
+
+
+
+GameBoardView (CS520 - Homework 1)
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+您的浏览器已禁用 JavaScript。
+
+
+
+
+
+
+
+
+
+
+所有已实现的接口:
+View
+
+
+public class GameBoardView
+
extends Object
+implements View
+The GameBoardView class visualizes the game board of blocks.
+
+ NOTE) For the Composite design pattern, this class is-a Component (i.e.
+ View).
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+方法概要
+
+
所有方法 实例方法 具体方法
+
+
+
+
+
+
+
+
+
Returns the BlockIndex (pair of row and column) of the given block
+ if it is part of this game board and returns null otherwise.
+
+
void
+
+
+
void
+
+
+
Updates the block at the given row and column
+ after one of the player's moves.
+
+
+
+
+
+
从类继承的方法 java.lang.Object
+
clone , equals , finalize , getClass , hashCode , notify , notifyAll , toString , wait , wait , wait
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+方法详细资料
+
+
+
+
+
+
+updateBlock
+public void updateBlock (RowGameModel gameModel,
+ int row,
+ int column)
+Updates the block at the given row and column
+ after one of the player's moves.
+
+参数:
+gameModel - The RowGameModel containing the block
+row - The row that contains the block
+column - The column that contains the block
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/tictactoe/jdoc/view/GameStatusView.html b/tictactoe/jdoc/view/GameStatusView.html
new file mode 100644
index 00000000..edac1698
--- /dev/null
+++ b/tictactoe/jdoc/view/GameStatusView.html
@@ -0,0 +1,201 @@
+
+
+
+
+GameStatusView (CS520 - Homework 1)
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+您的浏览器已禁用 JavaScript。
+
+
+
+
+
+
+
+
+
+
+所有已实现的接口:
+View
+
+
+public class GameStatusView
+
extends Object
+implements View
+The GameStatusView class visualizes the game status as either in progress,
+ current player's turn, or finished, either win or tie.
+
+ NOTE) For the Composite design pattern, this class is-a Component (i.e. View).
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+方法概要
+
+
+
从类继承的方法 java.lang.Object
+
clone , equals , finalize , getClass , hashCode , notify , notifyAll , toString , wait , wait , wait
+
+
+
+
+
+
+
+
+
+
+
+
+
+构造器详细资料
+
+
+
+GameStatusView
+public GameStatusView (JPanel messages)
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/tictactoe/jdoc/view/RowGameGUI.html b/tictactoe/jdoc/view/RowGameGUI.html
new file mode 100644
index 00000000..b736b82f
--- /dev/null
+++ b/tictactoe/jdoc/view/RowGameGUI.html
@@ -0,0 +1,268 @@
+
+
+
+
+RowGameGUI (CS520 - Homework 1)
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+您的浏览器已禁用 JavaScript。
+
+
+
+
+
+
+
+
+
+
+所有已实现的接口:
+View
+
+
+public class RowGameGUI
+
extends Object
+implements View
+The RowGameGUI class is applying the Composite design pattern.
+ This class is the Composite. The class also is-a Component (i.e. View).
+
+
+
+
+
+
+字段概要
+字段
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
For the Composite design pattern, the RowGameGUI is the Composite
+
+
+
+
+
+
+
+构造器概要
+构造器
+
+
+
+
+
+
Creates a new game initializing the GUI.
+
+
+
+
+
+
+
+方法概要
+
+
所有方法 实例方法 具体方法
+
+
+
+
+
+
void
+
+
+
+
+
+
void
+
+
+
+
+
+
+
从类继承的方法 java.lang.Object
+
clone , equals , finalize , getClass , hashCode , notify , notifyAll , toString , wait , wait , wait
+
+
+
+
+
+
+
+
+
+字段详细资料
+
+
+
+
+
+
+
+
+
+
+
+
+viewList
+
+For the Composite design pattern, the RowGameGUI is the Composite
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+构造器详细资料
+
+
+
+RowGameGUI
+
+Creates a new game initializing the GUI.
+
+
+
+
+
+
+
+
+方法详细资料
+
+
+
+
+
+
+addView
+public void addView (View view)
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/tictactoe/jdoc/view/View.html b/tictactoe/jdoc/view/View.html
new file mode 100644
index 00000000..ebc067af
--- /dev/null
+++ b/tictactoe/jdoc/view/View.html
@@ -0,0 +1,132 @@
+
+
+
+
+View (CS520 - Homework 1)
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+您的浏览器已禁用 JavaScript。
+
+
+
+
+
+
+
+
+
+所有已知实现类:
+GameBoardView , GameStatusView , RowGameGUI
+
+
+public interface View
+The View interfaces supports updating the visualizations of the Model.
+
+ NOTE) For the Composite design pattern, the View interface is the Component interface.
+
+
+
+
+
+
+
+
+
diff --git a/tictactoe/jdoc/view/class-use/BlockIndex.html b/tictactoe/jdoc/view/class-use/BlockIndex.html
new file mode 100644
index 00000000..baa3bb79
--- /dev/null
+++ b/tictactoe/jdoc/view/class-use/BlockIndex.html
@@ -0,0 +1,89 @@
+
+
+
+
+类 view.BlockIndex的使用 (CS520 - Homework 1)
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+您的浏览器已禁用 JavaScript。
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
Returns the BlockIndex (pair of row and column) of the given block
+ if it is part of this game board and returns null otherwise.
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/tictactoe/jdoc/view/class-use/GameBoardView.html b/tictactoe/jdoc/view/class-use/GameBoardView.html
new file mode 100644
index 00000000..038928f3
--- /dev/null
+++ b/tictactoe/jdoc/view/class-use/GameBoardView.html
@@ -0,0 +1,83 @@
+
+
+
+
+类 view.GameBoardView的使用 (CS520 - Homework 1)
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+您的浏览器已禁用 JavaScript。
+
+
+
+
diff --git a/tictactoe/jdoc/view/class-use/GameStatusView.html b/tictactoe/jdoc/view/class-use/GameStatusView.html
new file mode 100644
index 00000000..2abc7026
--- /dev/null
+++ b/tictactoe/jdoc/view/class-use/GameStatusView.html
@@ -0,0 +1,58 @@
+
+
+
+
+类 view.GameStatusView的使用 (CS520 - Homework 1)
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+您的浏览器已禁用 JavaScript。
+
+
+
+
+
+
+没有view.GameStatusView的用法
+
+
+
+
diff --git a/tictactoe/jdoc/view/class-use/RowGameGUI.html b/tictactoe/jdoc/view/class-use/RowGameGUI.html
new file mode 100644
index 00000000..51f52ed1
--- /dev/null
+++ b/tictactoe/jdoc/view/class-use/RowGameGUI.html
@@ -0,0 +1,83 @@
+
+
+
+
+类 view.RowGameGUI的使用 (CS520 - Homework 1)
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+您的浏览器已禁用 JavaScript。
+
+
+
+
diff --git a/tictactoe/jdoc/view/class-use/View.html b/tictactoe/jdoc/view/class-use/View.html
new file mode 100644
index 00000000..4a90a6fd
--- /dev/null
+++ b/tictactoe/jdoc/view/class-use/View.html
@@ -0,0 +1,116 @@
+
+
+
+
+接口 view.View的使用 (CS520 - Homework 1)
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+您的浏览器已禁用 JavaScript。
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
class
+
+
+
The GameBoardView class visualizes the game board of blocks.
+
+
class
+
+
+
The GameStatusView class visualizes the game status as either in progress,
+ current player's turn, or finished, either win or tie.
+
+
class
+
+
+
The RowGameGUI class is applying the Composite design pattern.
+
+
+
+
+
+
+
+
+
+
+
For the Composite design pattern, the RowGameGUI is the Composite
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/tictactoe/jdoc/view/package-summary.html b/tictactoe/jdoc/view/package-summary.html
new file mode 100644
index 00000000..bc7ecdd4
--- /dev/null
+++ b/tictactoe/jdoc/view/package-summary.html
@@ -0,0 +1,106 @@
+
+
+
+
+view (CS520 - Homework 1)
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+您的浏览器已禁用 JavaScript。
+
+
+
+
+
+
+
+package view
+
+
+
+
+
All Classes and Interfaces 接口 类
+
+
+
+
+
+
+
+
+
The GameBoardView class visualizes the game board of blocks.
+
+
+
+
The GameStatusView class visualizes the game status as either in progress,
+ current player's turn, or finished, either win or tie.
+
+
+
+
The RowGameGUI class is applying the Composite design pattern.
+
+
+
+
The View interfaces supports updating the visualizations of the Model.
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/tictactoe/jdoc/view/package-tree.html b/tictactoe/jdoc/view/package-tree.html
new file mode 100644
index 00000000..683a5ddc
--- /dev/null
+++ b/tictactoe/jdoc/view/package-tree.html
@@ -0,0 +1,81 @@
+
+
+
+
+view 类分层结构 (CS520 - Homework 1)
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+您的浏览器已禁用 JavaScript。
+
+
+
+
diff --git a/tictactoe/jdoc/view/package-use.html b/tictactoe/jdoc/view/package-use.html
new file mode 100644
index 00000000..26965e56
--- /dev/null
+++ b/tictactoe/jdoc/view/package-use.html
@@ -0,0 +1,103 @@
+
+
+
+
+程序包 view的使用 (CS520 - Homework 1)
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+您的浏览器已禁用 JavaScript。
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
The RowGameGUI class is applying the Composite design pattern.
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
The GameBoardView class visualizes the game board of blocks.
+
+
+
+
The View interfaces supports updating the visualizations of the Model.
+
+
+
+
+
+
+
+
+
+
+
diff --git a/tictactoe/src/controller/RowGameController.java b/tictactoe/src/controller/RowGameController.java
index 84e6ee28..daad037b 100644
--- a/tictactoe/src/controller/RowGameController.java
+++ b/tictactoe/src/controller/RowGameController.java
@@ -13,373 +13,506 @@
import view.RowGameGUI;
public class RowGameController {
- public RowGameModel gameModel;
- public RowGameGUI gameView;
+ public RowGameModel gameModel;
+ public RowGameGUI gameView;
- /**
- * Creates a new game initializing the GUI.
- */
- public RowGameController() {
- gameModel = new RowGameModel();
- gameView = new RowGameGUI(this);
+ // Add a new button to the GUI for undo functionality
+ private JButton undo = new JButton("Undo");
- for(int row = 0; row<3; row++) {
- for(int column = 0; column<3 ;column++) {
- gameModel.blocksData[row][column].setContents("");
- gameModel.blocksData[row][column].setIsLegalMove(true);
- }
- }
+ /**
+ * Creates a new game initializing the GUI.
+ */
+ public RowGameController() {
+ gameModel = new RowGameModel();
+ gameView = new RowGameGUI(this);
+ ///////////////
+ // add undo button to the GUI
+ // gameView.gui.add(undo, BorderLayout.SOUTH);
- gameView.update(gameModel);
- }
+ // add action listener to the undo button
+ // undo.addActionListener(new ActionListener() {
+ // public void actionPerformed(ActionEvent e) {
+ // undoMove();
+ // }
+ // });
+ ////////////////
+ for (int row = 0; row < 3; row++) {
+ for (int column = 0; column < 3; column++) {
+ gameModel.blocksData[row][column].setContents("");
+ gameModel.blocksData[row][column].setIsLegalMove(true);
+ }
+ }
- /**
- * Moves the current player into the given block.
- *
- * @param block The block to be moved to by the current player
- */
- public void move(JButton block) {
- // The Controller first manipulates the Model.
- gameModel.movesLeft--;
+ gameView.update(gameModel);
+ }
- BlockIndex blockIndex = gameView.getBlockIndex(block);
- if(gameModel.getPlayer().equals(Player.PLAYER_1)) {
- // Check whether player 1 won
- if(blockIndex.matches(0, 0)) {
- gameModel.blocksData[0][0].setContents("X");
- gameModel.blocksData[0][0].setIsLegalMove(false);
- gameModel.setPlayer(Player.PLAYER_2);
- if(gameModel.movesLeft<7) {
- if((gameModel.blocksData[0][0].getContents().equals(gameModel.blocksData[0][1].getContents()) &&
- gameModel.blocksData[0][1].getContents().equals(gameModel.blocksData[0][2].getContents())) ||
- (gameModel.blocksData[0][0].getContents().equals(gameModel.blocksData[1][0].getContents()) &&
- gameModel.blocksData[1][0].getContents().equals(gameModel.blocksData[2][0].getContents())) ||
- (gameModel.blocksData[0][0].getContents().equals(gameModel.blocksData[1][1].getContents()) &&
- gameModel.blocksData[1][1].getContents().equals(gameModel.blocksData[2][2].getContents()))) {
- gameModel.setFinalResult("Player " + Player.PLAYER_1 + " wins!");
- endGame();
- } else if(gameModel.movesLeft==0) {
- gameModel.setFinalResult(RowGameModel.GAME_END_NOWINNER);
- }
- }
- } else if(blockIndex.matches(0, 1)) {
- gameModel.blocksData[0][1].setContents("X");
- gameModel.blocksData[0][1].setIsLegalMove(false);
- gameModel.setPlayer(Player.PLAYER_2);
- if(gameModel.movesLeft<7) {
- if((gameModel.blocksData[0][1].getContents().equals(gameModel.blocksData[0][0].getContents()) &&
- gameModel.blocksData[0][0].getContents().equals(gameModel.blocksData[0][2].getContents())) ||
- (gameModel.blocksData[0][1].getContents().equals(gameModel.blocksData[1][1].getContents()) &&
- gameModel.blocksData[1][1].getContents().equals(gameModel.blocksData[2][1].getContents()))) {
- gameModel.setFinalResult("Player " + Player.PLAYER_1 + " wins!");
- endGame();
- } else if(gameModel.movesLeft==0) {
- gameModel.setFinalResult(RowGameModel.GAME_END_NOWINNER);
- }
- }
- } else if(blockIndex.matches(0, 2)) {
- gameModel.blocksData[0][2].setContents("X");
- gameModel.blocksData[0][2].setIsLegalMove(false);
- gameModel.setPlayer(Player.PLAYER_2);
- if(gameModel.movesLeft<7) {
- if((gameModel.blocksData[0][2].getContents().equals(gameModel.blocksData[0][1].getContents()) &&
- gameModel.blocksData[0][1].getContents().equals(gameModel.blocksData[0][0].getContents())) ||
- (gameModel.blocksData[0][2].getContents().equals(gameModel.blocksData[1][2].getContents()) &&
- gameModel.blocksData[1][2].getContents().equals(gameModel.blocksData[2][2].getContents())) ||
- (gameModel.blocksData[0][2].getContents().equals(gameModel.blocksData[1][1].getContents()) &&
- gameModel.blocksData[1][1].getContents().equals(gameModel.blocksData[2][0].getContents()))) {
- gameModel.setFinalResult("Player " + Player.PLAYER_1 + " wins!");
- endGame();
- } else if(gameModel.movesLeft==0) {
- gameModel.setFinalResult(RowGameModel.GAME_END_NOWINNER);
- }
- }
- } else if(blockIndex.matches(1, 0)) {
- gameModel.blocksData[1][0].setContents("X");
- gameModel.blocksData[1][0].setIsLegalMove(false);
- gameModel.setPlayer(Player.PLAYER_2);
- if(gameModel.movesLeft<7) {
- if((gameModel.blocksData[1][0].getContents().equals(gameModel.blocksData[1][1].getContents()) &&
- gameModel.blocksData[1][1].getContents().equals(gameModel.blocksData[1][2].getContents())) ||
- (gameModel.blocksData[1][0].getContents().equals(gameModel.blocksData[0][0].getContents()) &&
- gameModel.blocksData[0][0].getContents().equals(gameModel.blocksData[2][0].getContents()))) {
- gameModel.setFinalResult("Player " + Player.PLAYER_1 + " wins!");
- endGame();
- } else if(gameModel.movesLeft==0) {
- gameModel.setFinalResult(RowGameModel.GAME_END_NOWINNER);
- }
- }
- } else if(blockIndex.matches(1, 1)) {
- gameModel.blocksData[1][1].setContents("X");
- gameModel.blocksData[1][1].setIsLegalMove(false);
- gameModel.setPlayer(Player.PLAYER_2);
- if(gameModel.movesLeft<7) {
- if((gameModel.blocksData[1][1].getContents().equals(gameModel.blocksData[1][0].getContents()) &&
- gameModel.blocksData[1][0].getContents().equals(gameModel.blocksData[1][2].getContents())) ||
- (gameModel.blocksData[1][1].getContents().equals(gameModel.blocksData[0][1].getContents()) &&
- gameModel.blocksData[0][1].getContents().equals(gameModel.blocksData[2][1].getContents())) ||
- (gameModel.blocksData[1][1].getContents().equals(gameModel.blocksData[0][0].getContents()) &&
- gameModel.blocksData[0][0].getContents().equals(gameModel.blocksData[2][2].getContents())) ||
- (gameModel.blocksData[1][1].getContents().equals(gameModel.blocksData[0][2].getContents()) &&
- gameModel.blocksData[0][2].getContents().equals(gameModel.blocksData[2][0].getContents()))) {
- gameModel.setFinalResult("Player " + Player.PLAYER_1 + " wins!");
- endGame();
- } else if(gameModel.movesLeft==0) {
- gameModel.setFinalResult(RowGameModel.GAME_END_NOWINNER);
- }
- }
- } else if(blockIndex.matches(1, 2)) {
- gameModel.blocksData[1][2].setContents("X");
- gameModel.blocksData[1][2].setIsLegalMove(false);
- gameModel.setPlayer(Player.PLAYER_2);
- if(gameModel.movesLeft<7) {
- if((gameModel.blocksData[1][2].getContents().equals(gameModel.blocksData[0][2].getContents()) &&
- gameModel.blocksData[0][2].getContents().equals(gameModel.blocksData[2][2].getContents())) ||
- (gameModel.blocksData[1][2].getContents().equals(gameModel.blocksData[1][1].getContents()) &&
- gameModel.blocksData[1][1].getContents().equals(gameModel.blocksData[1][0].getContents()))) {
- gameModel.setFinalResult("Player " + Player.PLAYER_1 + " wins!");
- endGame();
- } else if(gameModel.movesLeft==0) {
- gameModel.setFinalResult(RowGameModel.GAME_END_NOWINNER);
- }
- }
- } else if(blockIndex.matches(2, 0)) {
- gameModel.blocksData[2][0].setContents("X");
- gameModel.blocksData[2][0].setIsLegalMove(false);
- gameModel.setPlayer(Player.PLAYER_2);
- if(gameModel.movesLeft<7) {
- if((gameModel.blocksData[2][0].getContents().equals(gameModel.blocksData[2][1].getContents()) &&
- gameModel.blocksData[2][1].getContents().equals(gameModel.blocksData[2][2].getContents())) ||
- (gameModel.blocksData[2][0].getContents().equals(gameModel.blocksData[1][0].getContents()) &&
- gameModel.blocksData[1][0].getContents().equals(gameModel.blocksData[0][0].getContents())) ||
- (gameModel.blocksData[2][0].getContents().equals(gameModel.blocksData[1][1].getContents()) &&
- gameModel.blocksData[1][1].getContents().equals(gameModel.blocksData[0][2].getContents()))) {
- gameModel.setFinalResult("Player " + Player.PLAYER_1 + " wins!");
- endGame();
- } else if(gameModel.movesLeft==0) {
- gameModel.setFinalResult(RowGameModel.GAME_END_NOWINNER);
- }
- }
- } else if(blockIndex.matches(2, 1)) {
- gameModel.blocksData[2][1].setContents("X");
- gameModel.blocksData[2][1].setIsLegalMove(false);
- gameModel.setPlayer(Player.PLAYER_2);
- if(gameModel.movesLeft<7) {
- if((gameModel.blocksData[2][1].getContents().equals(gameModel.blocksData[2][0].getContents()) &&
- gameModel.blocksData[2][0].getContents().equals(gameModel.blocksData[2][2].getContents())) ||
- (gameModel.blocksData[2][1].getContents().equals(gameModel.blocksData[1][1].getContents()) &&
- gameModel.blocksData[1][1].getContents().equals(gameModel.blocksData[0][1].getContents()))) {
- gameModel.setFinalResult("Player " + Player.PLAYER_1 + " wins!");
- endGame();
- } else if(gameModel.movesLeft==0) {
- gameModel.setFinalResult(RowGameModel.GAME_END_NOWINNER);
- }
- }
- } else if(blockIndex.matches(2, 2)) {
- gameModel.blocksData[2][2].setContents("X");
- gameModel.blocksData[2][2].setIsLegalMove(false);
- gameModel.setPlayer(Player.PLAYER_2);
- if(gameModel.movesLeft<7) {
- if((gameModel.blocksData[2][2].getContents().equals(gameModel.blocksData[2][1].getContents()) &&
- gameModel.blocksData[2][1].getContents().equals(gameModel.blocksData[2][0].getContents())) ||
- (gameModel.blocksData[2][2].getContents().equals(gameModel.blocksData[1][2].getContents()) &&
- gameModel.blocksData[1][2].getContents().equals(gameModel.blocksData[0][2].getContents())) ||
- (gameModel.blocksData[2][2].getContents().equals(gameModel.blocksData[1][1].getContents()) &&
- gameModel.blocksData[1][1].getContents().equals(gameModel.blocksData[0][0].getContents()))) {
- gameModel.setFinalResult("Player " + Player.PLAYER_1 + " wins!");
- endGame();
- } else if(gameModel.movesLeft==0) {
- gameModel.setFinalResult(RowGameModel.GAME_END_NOWINNER);
- }
- }
- }
- } else {
- // Check whether player 2 won
- if(blockIndex.matches(0, 0)) {
- gameModel.blocksData[0][0].setContents("O");
- gameModel.blocksData[0][0].setIsLegalMove(false);
- gameModel.setPlayer(Player.PLAYER_1);
- if(gameModel.movesLeft<7) {
- if((gameModel.blocksData[0][0].getContents().equals(gameModel.blocksData[0][1].getContents()) &&
- gameModel.blocksData[0][1].getContents().equals(gameModel.blocksData[0][2].getContents())) ||
- (gameModel.blocksData[0][0].getContents().equals(gameModel.blocksData[1][0].getContents()) &&
- gameModel.blocksData[1][0].getContents().equals(gameModel.blocksData[2][0].getContents())) ||
- (gameModel.blocksData[0][0].getContents().equals(gameModel.blocksData[1][1].getContents()) &&
- gameModel.blocksData[1][1].getContents().equals(gameModel.blocksData[2][2].getContents()))) {
- gameModel.setFinalResult("Player " + Player.PLAYER_2 + " wins!");
- endGame();
- } else if(gameModel.movesLeft==0) {
- gameModel.setFinalResult(RowGameModel.GAME_END_NOWINNER);
- }
- }
- } else if(blockIndex.matches(0, 1)) {
- gameModel.blocksData[0][1].setContents("O");
- gameModel.blocksData[0][1].setIsLegalMove(false);
- gameModel.setPlayer(Player.PLAYER_1);
- if(gameModel.movesLeft<7) {
- if((gameModel.blocksData[0][1].getContents().equals(gameModel.blocksData[0][0].getContents()) &&
- gameModel.blocksData[0][0].getContents().equals(gameModel.blocksData[0][2].getContents())) ||
- (gameModel.blocksData[0][1].getContents().equals(gameModel.blocksData[1][1].getContents()) &&
- gameModel.blocksData[1][1].getContents().equals(gameModel.blocksData[2][1].getContents()))) {
- gameModel.setFinalResult("Player " + Player.PLAYER_2 + " wins!");
- endGame();
- } else if(gameModel.movesLeft==0) {
- gameModel.setFinalResult(RowGameModel.GAME_END_NOWINNER);
- }
- }
- } else if(blockIndex.matches(0, 2)) {
- gameModel.blocksData[0][2].setContents("O");
- gameModel.blocksData[0][2].setIsLegalMove(false);
- gameModel.setPlayer(Player.PLAYER_1);
- if(gameModel.movesLeft<7) {
- if((gameModel.blocksData[0][2].getContents().equals(gameModel.blocksData[0][1].getContents()) &&
- gameModel.blocksData[0][1].getContents().equals(gameModel.blocksData[0][0].getContents())) ||
- (gameModel.blocksData[0][2].getContents().equals(gameModel.blocksData[1][2].getContents()) &&
- gameModel.blocksData[1][2].getContents().equals(gameModel.blocksData[2][2].getContents())) ||
- (gameModel.blocksData[0][2].getContents().equals(gameModel.blocksData[1][1].getContents()) &&
- gameModel.blocksData[1][1].getContents().equals(gameModel.blocksData[2][0].getContents()))) {
- gameModel.setFinalResult("Player " + Player.PLAYER_2 + " wins!");
- endGame();
- } else if(gameModel.movesLeft==0) {
- gameModel.setFinalResult(RowGameModel.GAME_END_NOWINNER);
- }
- }
- } else if(blockIndex.matches(1, 0)) {
- gameModel.blocksData[1][0].setContents("O");
- gameModel.blocksData[1][0].setIsLegalMove(false);
- gameModel.setPlayer(Player.PLAYER_1);
- if(gameModel.movesLeft<7) {
- if((gameModel.blocksData[1][0].getContents().equals(gameModel.blocksData[1][1].getContents()) &&
- gameModel.blocksData[1][1].getContents().equals(gameModel.blocksData[1][2].getContents())) ||
- (gameModel.blocksData[1][0].getContents().equals(gameModel.blocksData[0][0].getContents()) &&
- gameModel.blocksData[0][0].getContents().equals(gameModel.blocksData[2][0].getContents()))) {
- gameModel.setFinalResult("Player " + Player.PLAYER_2 + " wins!");
- endGame();
- } else if(gameModel.movesLeft==0) {
- gameModel.setFinalResult(RowGameModel.GAME_END_NOWINNER);
- }
- }
- } else if(blockIndex.matches(1, 1)) {
- gameModel.blocksData[1][1].setContents("O");
- gameModel.blocksData[1][1].setIsLegalMove(false);
- gameModel.setPlayer(Player.PLAYER_1);
- if(gameModel.movesLeft<7) {
- if((gameModel.blocksData[1][1].getContents().equals(gameModel.blocksData[1][0].getContents()) &&
- gameModel.blocksData[1][0].getContents().equals(gameModel.blocksData[1][2].getContents())) ||
- (gameModel.blocksData[1][1].getContents().equals(gameModel.blocksData[0][1].getContents()) &&
- gameModel.blocksData[0][1].getContents().equals(gameModel.blocksData[2][1].getContents())) ||
- (gameModel.blocksData[1][1].getContents().equals(gameModel.blocksData[0][0].getContents()) &&
- gameModel.blocksData[0][0].getContents().equals(gameModel.blocksData[2][2].getContents())) ||
- (gameModel.blocksData[1][1].getContents().equals(gameModel.blocksData[0][2].getContents()) &&
- gameModel.blocksData[0][2].getContents().equals(gameModel.blocksData[2][0].getContents()))) {
- gameModel.setFinalResult("Player " + Player.PLAYER_2 + " wins!");
- endGame();
- } else if(gameModel.movesLeft==0) {
- gameModel.setFinalResult(RowGameModel.GAME_END_NOWINNER);
- }
- }
- } else if(blockIndex.matches(1, 2)) {
- gameModel.blocksData[1][2].setContents("O");
- gameModel.blocksData[1][2].setIsLegalMove(false);
- gameModel.setPlayer(Player.PLAYER_1);
- if(gameModel.movesLeft<7) {
- if((gameModel.blocksData[1][2].getContents().equals(gameModel.blocksData[0][2].getContents()) &&
- gameModel.blocksData[0][2].getContents().equals(gameModel.blocksData[2][2].getContents())) ||
- (gameModel.blocksData[1][2].getContents().equals(gameModel.blocksData[1][1].getContents()) &&
- gameModel.blocksData[1][1].getContents().equals(gameModel.blocksData[1][0].getContents()))) {
- gameModel.setFinalResult("Player " + Player.PLAYER_2 + " wins!");
- endGame();
- } else if(gameModel.movesLeft==0) {
- gameModel.setFinalResult(RowGameModel.GAME_END_NOWINNER);
- }
- }
- } else if(blockIndex.matches(2, 0)) {
- gameModel.blocksData[2][0].setContents("O");
- gameModel.blocksData[2][0].setIsLegalMove(false);
- gameModel.setPlayer(Player.PLAYER_1);
- if(gameModel.movesLeft<7) {
- if((gameModel.blocksData[2][0].getContents().equals(gameModel.blocksData[2][1].getContents()) &&
- gameModel.blocksData[2][1].getContents().equals(gameModel.blocksData[2][2].getContents())) ||
- (gameModel.blocksData[2][0].getContents().equals(gameModel.blocksData[1][0].getContents()) &&
- gameModel.blocksData[1][0].getContents().equals(gameModel.blocksData[0][0].getContents())) ||
- (gameModel.blocksData[2][0].getContents().equals(gameModel.blocksData[1][1].getContents()) &&
- gameModel.blocksData[1][1].getContents().equals(gameModel.blocksData[0][2].getContents()))) {
- gameModel.setFinalResult("Player " + Player.PLAYER_2 + " wins!");
- endGame();
- } else if(gameModel.movesLeft==0) {
- gameModel.setFinalResult(RowGameModel.GAME_END_NOWINNER);
- }
- }
- } else if(blockIndex.matches(2, 1)) {
- gameModel.blocksData[2][1].setContents("O");
- gameModel.blocksData[2][1].setIsLegalMove(false);
- gameModel.setPlayer(Player.PLAYER_1);
- if(gameModel.movesLeft<7) {
- if((gameModel.blocksData[2][1].getContents().equals(gameModel.blocksData[2][0].getContents()) &&
- gameModel.blocksData[2][0].getContents().equals(gameModel.blocksData[2][2].getContents())) ||
- (gameModel.blocksData[2][1].getContents().equals(gameModel.blocksData[1][1].getContents()) &&
- gameModel.blocksData[1][1].getContents().equals(gameModel.blocksData[0][1].getContents()))) {
- gameModel.setFinalResult("Player " + Player.PLAYER_2 + " wins!");
- endGame();
- } else if(gameModel.movesLeft==0) {
- gameModel.setFinalResult(RowGameModel.GAME_END_NOWINNER);
- }
- }
- } else if(blockIndex.matches(2, 2)) {
- gameModel.blocksData[2][2].setContents("O");
- gameModel.blocksData[2][2].setIsLegalMove(false);
- gameModel.setPlayer(Player.PLAYER_1);
- if(gameModel.movesLeft<7) {
- if((gameModel.blocksData[2][2].getContents().equals(gameModel.blocksData[2][1].getContents()) &&
- gameModel.blocksData[2][1].getContents().equals(gameModel.blocksData[2][0].getContents())) ||
- (gameModel.blocksData[2][2].getContents().equals(gameModel.blocksData[1][2].getContents()) &&
- gameModel.blocksData[1][2].getContents().equals(gameModel.blocksData[0][2].getContents())) ||
- (gameModel.blocksData[2][2].getContents().equals(gameModel.blocksData[1][1].getContents()) &&
- gameModel.blocksData[1][1].getContents().equals(gameModel.blocksData[0][0].getContents()))) {
- gameModel.setFinalResult("Player " + Player.PLAYER_2 + " wins!");
- endGame();
- } else if(gameModel.movesLeft==0) {
- gameModel.setFinalResult(RowGameModel.GAME_END_NOWINNER);
- }
+ //////////////
+ public void undoMove() {
+ if (gameModel.movesLeft == 9) {
+
+ throw new IllegalStateException("Cannot undo before making a move");
+ } else if (gameModel.movesLeft < 9) {
+ gameModel.undoMove(); // call the undoMove() method of the model
+ gameView.update(gameModel); // update the view with the new model state
}
- }
}
+ //////////////
+
+ /**
+ * Moves the current player into the given block.
+ *
+ * @param block The block to be moved to by the current player
+ */
+ public void move(JButton block) {
+ // The Controller first manipulates the Model.
+ gameModel.movesLeft--;
- // The Controller then updates the View.
- gameView.update(gameModel);
- }
+ BlockIndex blockIndex = gameView.getBlockIndex(block);
+ if (gameModel.getPlayer().equals(Player.PLAYER_1)) {
+ // Check whether player 1 won
+ if (blockIndex.matches(0, 0)) {
+ gameModel.blocksData[0][0].setContents("X");
+ gameModel.blocksData[0][0].setIsLegalMove(false);
+ gameModel.setPlayer(Player.PLAYER_2);
+ gameModel.recordMove(0, 0, Player.PLAYER_1);
+ if (gameModel.movesLeft < 7) {
+ if ((gameModel.blocksData[0][0].getContents().equals(gameModel.blocksData[0][1].getContents()) &&
+ gameModel.blocksData[0][1].getContents().equals(gameModel.blocksData[0][2].getContents()))
+ ||
+ (gameModel.blocksData[0][0].getContents().equals(gameModel.blocksData[1][0].getContents())
+ &&
+ gameModel.blocksData[1][0].getContents()
+ .equals(gameModel.blocksData[2][0].getContents()))
+ ||
+ (gameModel.blocksData[0][0].getContents().equals(gameModel.blocksData[1][1].getContents())
+ &&
+ gameModel.blocksData[1][1].getContents()
+ .equals(gameModel.blocksData[2][2].getContents()))) {
+ gameModel.setFinalResult("Player " + Player.PLAYER_1 + " wins!");
+ endGame();
+ } else if (gameModel.movesLeft == 0) {
+ gameModel.setFinalResult(RowGameModel.GAME_END_NOWINNER);
+ }
+ }
+ } else if (blockIndex.matches(0, 1)) {
+ gameModel.blocksData[0][1].setContents("X");
+ gameModel.blocksData[0][1].setIsLegalMove(false);
+ gameModel.setPlayer(Player.PLAYER_2);
+ gameModel.recordMove(0, 1, Player.PLAYER_1);
+ if (gameModel.movesLeft < 7) {
+ if ((gameModel.blocksData[0][1].getContents().equals(gameModel.blocksData[0][0].getContents()) &&
+ gameModel.blocksData[0][0].getContents().equals(gameModel.blocksData[0][2].getContents()))
+ ||
+ (gameModel.blocksData[0][1].getContents().equals(gameModel.blocksData[1][1].getContents())
+ &&
+ gameModel.blocksData[1][1].getContents()
+ .equals(gameModel.blocksData[2][1].getContents()))) {
+ gameModel.setFinalResult("Player " + Player.PLAYER_1 + " wins!");
+ endGame();
+ } else if (gameModel.movesLeft == 0) {
+ gameModel.setFinalResult(RowGameModel.GAME_END_NOWINNER);
+ }
+ }
+ } else if (blockIndex.matches(0, 2)) {
+ gameModel.blocksData[0][2].setContents("X");
+ gameModel.blocksData[0][2].setIsLegalMove(false);
+ gameModel.setPlayer(Player.PLAYER_2);
+ gameModel.recordMove(0, 2, Player.PLAYER_1);
+ if (gameModel.movesLeft < 7) {
+ if ((gameModel.blocksData[0][2].getContents().equals(gameModel.blocksData[0][1].getContents()) &&
+ gameModel.blocksData[0][1].getContents().equals(gameModel.blocksData[0][0].getContents()))
+ ||
+ (gameModel.blocksData[0][2].getContents().equals(gameModel.blocksData[1][2].getContents())
+ &&
+ gameModel.blocksData[1][2].getContents()
+ .equals(gameModel.blocksData[2][2].getContents()))
+ ||
+ (gameModel.blocksData[0][2].getContents().equals(gameModel.blocksData[1][1].getContents())
+ &&
+ gameModel.blocksData[1][1].getContents()
+ .equals(gameModel.blocksData[2][0].getContents()))) {
+ gameModel.setFinalResult("Player " + Player.PLAYER_1 + " wins!");
+ endGame();
+ } else if (gameModel.movesLeft == 0) {
+ gameModel.setFinalResult(RowGameModel.GAME_END_NOWINNER);
+ }
+ }
+ } else if (blockIndex.matches(1, 0)) {
+ gameModel.blocksData[1][0].setContents("X");
+ gameModel.blocksData[1][0].setIsLegalMove(false);
+ gameModel.setPlayer(Player.PLAYER_2);
+ gameModel.recordMove(1, 0, Player.PLAYER_1);
+ if (gameModel.movesLeft < 7) {
+ if ((gameModel.blocksData[1][0].getContents().equals(gameModel.blocksData[1][1].getContents()) &&
+ gameModel.blocksData[1][1].getContents().equals(gameModel.blocksData[1][2].getContents()))
+ ||
+ (gameModel.blocksData[1][0].getContents().equals(gameModel.blocksData[0][0].getContents())
+ &&
+ gameModel.blocksData[0][0].getContents()
+ .equals(gameModel.blocksData[2][0].getContents()))) {
+ gameModel.setFinalResult("Player " + Player.PLAYER_1 + " wins!");
+ endGame();
+ } else if (gameModel.movesLeft == 0) {
+ gameModel.setFinalResult(RowGameModel.GAME_END_NOWINNER);
+ }
+ }
+ } else if (blockIndex.matches(1, 1)) {
+ gameModel.blocksData[1][1].setContents("X");
+ gameModel.blocksData[1][1].setIsLegalMove(false);
+ gameModel.setPlayer(Player.PLAYER_2);
+ gameModel.recordMove(1, 1, Player.PLAYER_1);
+ if (gameModel.movesLeft < 7) {
+ if ((gameModel.blocksData[1][1].getContents().equals(gameModel.blocksData[1][0].getContents()) &&
+ gameModel.blocksData[1][0].getContents().equals(gameModel.blocksData[1][2].getContents()))
+ ||
+ (gameModel.blocksData[1][1].getContents().equals(gameModel.blocksData[0][1].getContents())
+ &&
+ gameModel.blocksData[0][1].getContents()
+ .equals(gameModel.blocksData[2][1].getContents()))
+ ||
+ (gameModel.blocksData[1][1].getContents().equals(gameModel.blocksData[0][0].getContents())
+ &&
+ gameModel.blocksData[0][0].getContents()
+ .equals(gameModel.blocksData[2][2].getContents()))
+ ||
+ (gameModel.blocksData[1][1].getContents().equals(gameModel.blocksData[0][2].getContents())
+ &&
+ gameModel.blocksData[0][2].getContents()
+ .equals(gameModel.blocksData[2][0].getContents()))) {
+ gameModel.setFinalResult("Player " + Player.PLAYER_1 + " wins!");
+ endGame();
+ } else if (gameModel.movesLeft == 0) {
+ gameModel.setFinalResult(RowGameModel.GAME_END_NOWINNER);
+ }
+ }
+ } else if (blockIndex.matches(1, 2)) {
+ gameModel.blocksData[1][2].setContents("X");
+ gameModel.blocksData[1][2].setIsLegalMove(false);
+ gameModel.setPlayer(Player.PLAYER_2);
+ gameModel.recordMove(1, 2, Player.PLAYER_1);
+ if (gameModel.movesLeft < 7) {
+ if ((gameModel.blocksData[1][2].getContents().equals(gameModel.blocksData[0][2].getContents()) &&
+ gameModel.blocksData[0][2].getContents().equals(gameModel.blocksData[2][2].getContents()))
+ ||
+ (gameModel.blocksData[1][2].getContents().equals(gameModel.blocksData[1][1].getContents())
+ &&
+ gameModel.blocksData[1][1].getContents()
+ .equals(gameModel.blocksData[1][0].getContents()))) {
+ gameModel.setFinalResult("Player " + Player.PLAYER_1 + " wins!");
+ endGame();
+ } else if (gameModel.movesLeft == 0) {
+ gameModel.setFinalResult(RowGameModel.GAME_END_NOWINNER);
+ }
+ }
+ } else if (blockIndex.matches(2, 0)) {
+ gameModel.blocksData[2][0].setContents("X");
+ gameModel.blocksData[2][0].setIsLegalMove(false);
+ gameModel.setPlayer(Player.PLAYER_2);
+ gameModel.recordMove(2, 0, Player.PLAYER_1);
+ if (gameModel.movesLeft < 7) {
+ if ((gameModel.blocksData[2][0].getContents().equals(gameModel.blocksData[2][1].getContents()) &&
+ gameModel.blocksData[2][1].getContents().equals(gameModel.blocksData[2][2].getContents()))
+ ||
+ (gameModel.blocksData[2][0].getContents().equals(gameModel.blocksData[1][0].getContents())
+ &&
+ gameModel.blocksData[1][0].getContents()
+ .equals(gameModel.blocksData[0][0].getContents()))
+ ||
+ (gameModel.blocksData[2][0].getContents().equals(gameModel.blocksData[1][1].getContents())
+ &&
+ gameModel.blocksData[1][1].getContents()
+ .equals(gameModel.blocksData[0][2].getContents()))) {
+ gameModel.setFinalResult("Player " + Player.PLAYER_1 + " wins!");
+ endGame();
+ } else if (gameModel.movesLeft == 0) {
+ gameModel.setFinalResult(RowGameModel.GAME_END_NOWINNER);
+ }
+ }
+ } else if (blockIndex.matches(2, 1)) {
+ gameModel.blocksData[2][1].setContents("X");
+ gameModel.blocksData[2][1].setIsLegalMove(false);
+ gameModel.setPlayer(Player.PLAYER_2);
+ gameModel.recordMove(2, 1, Player.PLAYER_1);
+ if (gameModel.movesLeft < 7) {
+ if ((gameModel.blocksData[2][1].getContents().equals(gameModel.blocksData[2][0].getContents()) &&
+ gameModel.blocksData[2][0].getContents().equals(gameModel.blocksData[2][2].getContents()))
+ ||
+ (gameModel.blocksData[2][1].getContents().equals(gameModel.blocksData[1][1].getContents())
+ &&
+ gameModel.blocksData[1][1].getContents()
+ .equals(gameModel.blocksData[0][1].getContents()))) {
+ gameModel.setFinalResult("Player " + Player.PLAYER_1 + " wins!");
+ endGame();
+ } else if (gameModel.movesLeft == 0) {
+ gameModel.setFinalResult(RowGameModel.GAME_END_NOWINNER);
+ }
+ }
+ } else if (blockIndex.matches(2, 2)) {
+ gameModel.blocksData[2][2].setContents("X");
+ gameModel.blocksData[2][2].setIsLegalMove(false);
+ gameModel.setPlayer(Player.PLAYER_2);
+ gameModel.recordMove(2, 2, Player.PLAYER_1);
+ if (gameModel.movesLeft < 7) {
+ if ((gameModel.blocksData[2][2].getContents().equals(gameModel.blocksData[2][1].getContents()) &&
+ gameModel.blocksData[2][1].getContents().equals(gameModel.blocksData[2][0].getContents()))
+ ||
+ (gameModel.blocksData[2][2].getContents().equals(gameModel.blocksData[1][2].getContents())
+ &&
+ gameModel.blocksData[1][2].getContents()
+ .equals(gameModel.blocksData[0][2].getContents()))
+ ||
+ (gameModel.blocksData[2][2].getContents().equals(gameModel.blocksData[1][1].getContents())
+ &&
+ gameModel.blocksData[1][1].getContents()
+ .equals(gameModel.blocksData[0][0].getContents()))) {
+ gameModel.setFinalResult("Player " + Player.PLAYER_1 + " wins!");
+ endGame();
+ } else if (gameModel.movesLeft == 0) {
+ gameModel.setFinalResult(RowGameModel.GAME_END_NOWINNER);
+ }
+ }
+ }
+ } else {
+ // Check whether player 2 won
+ if (blockIndex.matches(0, 0)) {
+ gameModel.blocksData[0][0].setContents("O");
+ gameModel.blocksData[0][0].setIsLegalMove(false);
+ gameModel.setPlayer(Player.PLAYER_1);
+ gameModel.recordMove(0, 0, Player.PLAYER_2);
+ if (gameModel.movesLeft < 7) {
+ if ((gameModel.blocksData[0][0].getContents().equals(gameModel.blocksData[0][1].getContents()) &&
+ gameModel.blocksData[0][1].getContents().equals(gameModel.blocksData[0][2].getContents()))
+ ||
+ (gameModel.blocksData[0][0].getContents().equals(gameModel.blocksData[1][0].getContents())
+ &&
+ gameModel.blocksData[1][0].getContents()
+ .equals(gameModel.blocksData[2][0].getContents()))
+ ||
+ (gameModel.blocksData[0][0].getContents().equals(gameModel.blocksData[1][1].getContents())
+ &&
+ gameModel.blocksData[1][1].getContents()
+ .equals(gameModel.blocksData[2][2].getContents()))) {
+ gameModel.setFinalResult("Player " + Player.PLAYER_2 + " wins!");
+ endGame();
+ } else if (gameModel.movesLeft == 0) {
+ gameModel.setFinalResult(RowGameModel.GAME_END_NOWINNER);
+ }
+ }
+ } else if (blockIndex.matches(0, 1)) {
+ gameModel.blocksData[0][1].setContents("O");
+ gameModel.blocksData[0][1].setIsLegalMove(false);
+ gameModel.setPlayer(Player.PLAYER_1);
+ gameModel.recordMove(0, 1, Player.PLAYER_2);
+ if (gameModel.movesLeft < 7) {
+ if ((gameModel.blocksData[0][1].getContents().equals(gameModel.blocksData[0][0].getContents()) &&
+ gameModel.blocksData[0][0].getContents().equals(gameModel.blocksData[0][2].getContents()))
+ ||
+ (gameModel.blocksData[0][1].getContents().equals(gameModel.blocksData[1][1].getContents())
+ &&
+ gameModel.blocksData[1][1].getContents()
+ .equals(gameModel.blocksData[2][1].getContents()))) {
+ gameModel.setFinalResult("Player " + Player.PLAYER_2 + " wins!");
+ endGame();
+ } else if (gameModel.movesLeft == 0) {
+ gameModel.setFinalResult(RowGameModel.GAME_END_NOWINNER);
+ }
+ }
+ } else if (blockIndex.matches(0, 2)) {
+ gameModel.blocksData[0][2].setContents("O");
+ gameModel.blocksData[0][2].setIsLegalMove(false);
+ gameModel.recordMove(0, 2, Player.PLAYER_2);
+ gameModel.setPlayer(Player.PLAYER_1);
+ if (gameModel.movesLeft < 7) {
+ if ((gameModel.blocksData[0][2].getContents().equals(gameModel.blocksData[0][1].getContents()) &&
+ gameModel.blocksData[0][1].getContents().equals(gameModel.blocksData[0][0].getContents()))
+ ||
+ (gameModel.blocksData[0][2].getContents().equals(gameModel.blocksData[1][2].getContents())
+ &&
+ gameModel.blocksData[1][2].getContents()
+ .equals(gameModel.blocksData[2][2].getContents()))
+ ||
+ (gameModel.blocksData[0][2].getContents().equals(gameModel.blocksData[1][1].getContents())
+ &&
+ gameModel.blocksData[1][1].getContents()
+ .equals(gameModel.blocksData[2][0].getContents()))) {
+ gameModel.setFinalResult("Player " + Player.PLAYER_2 + " wins!");
+ endGame();
+ } else if (gameModel.movesLeft == 0) {
+ gameModel.setFinalResult(RowGameModel.GAME_END_NOWINNER);
+ }
+ }
+ } else if (blockIndex.matches(1, 0)) {
+ gameModel.blocksData[1][0].setContents("O");
+ gameModel.blocksData[1][0].setIsLegalMove(false);
+ gameModel.setPlayer(Player.PLAYER_1);
+ gameModel.recordMove(1, 0, Player.PLAYER_2);
+ if (gameModel.movesLeft < 7) {
+ if ((gameModel.blocksData[1][0].getContents().equals(gameModel.blocksData[1][1].getContents()) &&
+ gameModel.blocksData[1][1].getContents().equals(gameModel.blocksData[1][2].getContents()))
+ ||
+ (gameModel.blocksData[1][0].getContents().equals(gameModel.blocksData[0][0].getContents())
+ &&
+ gameModel.blocksData[0][0].getContents()
+ .equals(gameModel.blocksData[2][0].getContents()))) {
+ gameModel.setFinalResult("Player " + Player.PLAYER_2 + " wins!");
+ endGame();
+ } else if (gameModel.movesLeft == 0) {
+ gameModel.setFinalResult(RowGameModel.GAME_END_NOWINNER);
+ }
+ }
+ } else if (blockIndex.matches(1, 1)) {
+ gameModel.blocksData[1][1].setContents("O");
+ gameModel.blocksData[1][1].setIsLegalMove(false);
+ gameModel.setPlayer(Player.PLAYER_1);
+ gameModel.recordMove(1, 1, Player.PLAYER_2);
+ if (gameModel.movesLeft < 7) {
+ if ((gameModel.blocksData[1][1].getContents().equals(gameModel.blocksData[1][0].getContents()) &&
+ gameModel.blocksData[1][0].getContents().equals(gameModel.blocksData[1][2].getContents()))
+ ||
+ (gameModel.blocksData[1][1].getContents().equals(gameModel.blocksData[0][1].getContents())
+ &&
+ gameModel.blocksData[0][1].getContents()
+ .equals(gameModel.blocksData[2][1].getContents()))
+ ||
+ (gameModel.blocksData[1][1].getContents().equals(gameModel.blocksData[0][0].getContents())
+ &&
+ gameModel.blocksData[0][0].getContents()
+ .equals(gameModel.blocksData[2][2].getContents()))
+ ||
+ (gameModel.blocksData[1][1].getContents().equals(gameModel.blocksData[0][2].getContents())
+ &&
+ gameModel.blocksData[0][2].getContents()
+ .equals(gameModel.blocksData[2][0].getContents()))) {
+ gameModel.setFinalResult("Player " + Player.PLAYER_2 + " wins!");
+ endGame();
+ } else if (gameModel.movesLeft == 0) {
+ gameModel.setFinalResult(RowGameModel.GAME_END_NOWINNER);
+ }
+ }
+ } else if (blockIndex.matches(1, 2)) {
+ gameModel.blocksData[1][2].setContents("O");
+ gameModel.blocksData[1][2].setIsLegalMove(false);
+ gameModel.setPlayer(Player.PLAYER_1);
+ gameModel.recordMove(1, 2, Player.PLAYER_2);
+ if (gameModel.movesLeft < 7) {
+ if ((gameModel.blocksData[1][2].getContents().equals(gameModel.blocksData[0][2].getContents()) &&
+ gameModel.blocksData[0][2].getContents().equals(gameModel.blocksData[2][2].getContents()))
+ ||
+ (gameModel.blocksData[1][2].getContents().equals(gameModel.blocksData[1][1].getContents())
+ &&
+ gameModel.blocksData[1][1].getContents()
+ .equals(gameModel.blocksData[1][0].getContents()))) {
+ gameModel.setFinalResult("Player " + Player.PLAYER_2 + " wins!");
+ endGame();
+ } else if (gameModel.movesLeft == 0) {
+ gameModel.setFinalResult(RowGameModel.GAME_END_NOWINNER);
+ }
+ }
+ } else if (blockIndex.matches(2, 0)) {
+ gameModel.blocksData[2][0].setContents("O");
+ gameModel.blocksData[2][0].setIsLegalMove(false);
+ gameModel.setPlayer(Player.PLAYER_1);
+ gameModel.recordMove(2, 0, Player.PLAYER_2);
+ if (gameModel.movesLeft < 7) {
+ if ((gameModel.blocksData[2][0].getContents().equals(gameModel.blocksData[2][1].getContents()) &&
+ gameModel.blocksData[2][1].getContents().equals(gameModel.blocksData[2][2].getContents()))
+ ||
+ (gameModel.blocksData[2][0].getContents().equals(gameModel.blocksData[1][0].getContents())
+ &&
+ gameModel.blocksData[1][0].getContents()
+ .equals(gameModel.blocksData[0][0].getContents()))
+ ||
+ (gameModel.blocksData[2][0].getContents().equals(gameModel.blocksData[1][1].getContents())
+ &&
+ gameModel.blocksData[1][1].getContents()
+ .equals(gameModel.blocksData[0][2].getContents()))) {
+ gameModel.setFinalResult("Player " + Player.PLAYER_2 + " wins!");
+ endGame();
+ } else if (gameModel.movesLeft == 0) {
+ gameModel.setFinalResult(RowGameModel.GAME_END_NOWINNER);
+ }
+ }
+ } else if (blockIndex.matches(2, 1)) {
+ gameModel.blocksData[2][1].setContents("O");
+ gameModel.blocksData[2][1].setIsLegalMove(false);
+ gameModel.setPlayer(Player.PLAYER_1);
+ gameModel.recordMove(2, 1, Player.PLAYER_2);
+ if (gameModel.movesLeft < 7) {
+ if ((gameModel.blocksData[2][1].getContents().equals(gameModel.blocksData[2][0].getContents()) &&
+ gameModel.blocksData[2][0].getContents().equals(gameModel.blocksData[2][2].getContents()))
+ ||
+ (gameModel.blocksData[2][1].getContents().equals(gameModel.blocksData[1][1].getContents())
+ &&
+ gameModel.blocksData[1][1].getContents()
+ .equals(gameModel.blocksData[0][1].getContents()))) {
+ gameModel.setFinalResult("Player " + Player.PLAYER_2 + " wins!");
+ endGame();
+ } else if (gameModel.movesLeft == 0) {
+ gameModel.setFinalResult(RowGameModel.GAME_END_NOWINNER);
+ }
+ }
+ } else if (blockIndex.matches(2, 2)) {
+ gameModel.blocksData[2][2].setContents("O");
+ gameModel.blocksData[2][2].setIsLegalMove(false);
+ gameModel.setPlayer(Player.PLAYER_1);
+ gameModel.recordMove(2, 2, Player.PLAYER_2);
+ if (gameModel.movesLeft < 7) {
+ if ((gameModel.blocksData[2][2].getContents().equals(gameModel.blocksData[2][1].getContents()) &&
+ gameModel.blocksData[2][1].getContents().equals(gameModel.blocksData[2][0].getContents()))
+ ||
+ (gameModel.blocksData[2][2].getContents().equals(gameModel.blocksData[1][2].getContents())
+ &&
+ gameModel.blocksData[1][2].getContents()
+ .equals(gameModel.blocksData[0][2].getContents()))
+ ||
+ (gameModel.blocksData[2][2].getContents().equals(gameModel.blocksData[1][1].getContents())
+ &&
+ gameModel.blocksData[1][1].getContents()
+ .equals(gameModel.blocksData[0][0].getContents()))) {
+ gameModel.setFinalResult("Player " + Player.PLAYER_2 + " wins!");
+ endGame();
+ } else if (gameModel.movesLeft == 0) {
+ gameModel.setFinalResult(RowGameModel.GAME_END_NOWINNER);
+ }
+ }
+ }
+ }
- /**
- * Ends the game disallowing further player turns.
- */
- public void endGame() {
- // The Controller first manipulates the Model.
- for(int row = 0;row<3;row++) {
- for(int column = 0;column<3;column++) {
- gameModel.blocksData[row][column].setIsLegalMove(false);
- }
+ // The Controller then updates the View.
+ gameView.update(gameModel);
}
- // The Controller then updates the View.
- gameView.update(gameModel);
- }
+ /**
+ * Ends the game disallowing further player turns.
+ */
+ public void endGame() {
+ // The Controller first manipulates the Model.
+ for (int row = 0; row < 3; row++) {
+ for (int column = 0; column < 3; column++) {
+ gameModel.blocksData[row][column].setIsLegalMove(false);
+ }
+ }
- /**
- * Resets the game to be able to start playing again.
- */
- public void resetGame() {
- // The Controller first manipulates the Model.
- for(int row = 0;row<3;row++) {
- for(int column = 0;column<3;column++) {
- gameModel.blocksData[row][column].reset();
- gameModel.blocksData[row][column].setIsLegalMove(true);
- }
- }
- gameModel.setPlayer(Player.PLAYER_1);
- gameModel.movesLeft = 9;
- gameModel.setFinalResult(null);
+ // The Controller then updates the View.
+ gameView.update(gameModel);
+ }
- // The Controller then updates the View.
- gameView.update(gameModel);
- }
+ /**
+ * Resets the game to be able to start playing again.
+ */
+ public void resetGame() {
+ // The Controller first manipulates the Model.
+ for (int row = 0; row < 3; row++) {
+ for (int column = 0; column < 3; column++) {
+ gameModel.blocksData[row][column].reset();
+ gameModel.blocksData[row][column].setIsLegalMove(true);
+ }
+ }
+ gameModel.setPlayer(Player.PLAYER_1);
+ gameModel.movesLeft = 9;
+ gameModel.setFinalResult(null);
+
+ // The Controller then updates the View.
+ gameView.update(gameModel);
+ }
}
diff --git a/tictactoe/src/model/RowBlockModel.java b/tictactoe/src/model/RowBlockModel.java
index f7029df1..672d251b 100644
--- a/tictactoe/src/model/RowBlockModel.java
+++ b/tictactoe/src/model/RowBlockModel.java
@@ -3,8 +3,7 @@
/**
* The TicTacToeBlock class represents a given block in the game.
*/
-public class RowBlockModel
-{
+public class RowBlockModel {
/**
* The game that contains this block
*/
@@ -27,18 +26,18 @@ public class RowBlockModel
* @throws IllegalArgumentException When the given game is null
*/
public RowBlockModel(RowGameModel game) {
- super();
+ super();
- if (game == null) {
- throw new IllegalArgumentException("The game must be non-null.");
- }
-
- this.game = game;
- this.reset();
+ if (game == null) {
+ throw new IllegalArgumentException("The game must be non-null.");
+ }
+
+ this.game = game;
+ this.reset();
}
public RowGameModel getGame() {
- return this.game;
+ return this.game;
}
/**
@@ -48,10 +47,10 @@ public RowGameModel getGame() {
* @throws IllegalArgumentException When the given value is null
*/
public void setContents(String value) {
- if (value == null) {
- throw new IllegalArgumentException("The value must be non-null.");
- }
- this.contents = value;
+ if (value == null) {
+ throw new IllegalArgumentException("The value must be non-null.");
+ }
+ this.contents = value;
}
/**
@@ -60,22 +59,22 @@ public void setContents(String value) {
* @return The non-null String value
*/
public String getContents() {
- return this.contents;
+ return this.contents;
}
public void setIsLegalMove(boolean isLegalMove) {
- this.isLegalMove = isLegalMove;
+ this.isLegalMove = isLegalMove;
}
public boolean getIsLegalMove() {
- return this.isLegalMove;
+ return this.isLegalMove;
}
/**
* Resets this block before starting a new game.
*/
public void reset() {
- this.contents = "";
- this.isLegalMove = false;
+ this.contents = "";
+ this.isLegalMove = false;
}
}
diff --git a/tictactoe/src/model/RowGameModel.java b/tictactoe/src/model/RowGameModel.java
index f9b15ec1..7c0bb325 100644
--- a/tictactoe/src/model/RowGameModel.java
+++ b/tictactoe/src/model/RowGameModel.java
@@ -1,8 +1,8 @@
package model;
+import java.util.Stack;
-public class RowGameModel
-{
+public class RowGameModel {
public static final String GAME_END_NOWINNER = "Game ends in a draw";
public RowBlockModel[][] blocksData = new RowBlockModel[3][3];
@@ -13,37 +13,98 @@ public class RowGameModel
private Player player = Player.PLAYER_1;
public int movesLeft = 9;
- private String finalResult = null;
+ public String finalResult = null;
+ private Stack moveHistory = new Stack<>(); // Stack to store move history
public RowGameModel() {
- super();
+ super();
- for (int row = 0; row < 3; row++) {
- for (int col = 0; col < 3; col++) {
- blocksData[row][col] = new RowBlockModel(this);
- } // end for col
- } // end for row
+ for (int row = 0; row < 3; row++) {
+ for (int col = 0; col < 3; col++) {
+ blocksData[row][col] = new RowBlockModel(this);
+ } // end for col
+ } // end for row
}
public Player getPlayer() {
- return this.player;
+ return this.player;
}
public void setPlayer(Player player) {
- // Perform input validation
- if (player == null) {
- throw new IllegalArgumentException("The player must be non-null.");
- }
+ // Perform input validation
+ if (player == null) {
+ throw new IllegalArgumentException("The player must be non-null.");
+ }
- this.player = player;
+ this.player = player;
}
-
+
public String getFinalResult() {
- return this.finalResult;
+ return this.finalResult;
}
public void setFinalResult(String finalResult) {
- this.finalResult = finalResult;
+ this.finalResult = finalResult;
+ }
+
+ /**
+ * Method to handle undo functionality. Allows undoing the previous move if
+ * there
+ * are moves to undo.
+ */
+ public void undoMove() {
+ if (!moveHistory.isEmpty()) { // Check if there are moves to undo
+ Move lastMove = moveHistory.pop(); // Pop the last move from the move history stack
+ int row = lastMove.getRow();
+ int col = lastMove.getCol();
+ Player player = lastMove.getPlayer();
+
+ // Undo the move by resetting the contents of the corresponding block
+ blocksData[row][col].reset();
+ blocksData[row][col].setIsLegalMove(true);
+
+ // Update the model state
+ this.player = player;
+ this.movesLeft++;
+ }
+ }
+
+ /**
+ * Method to record a move in the move history stack.
+ *
+ * @param row The row index of the block where the move was made
+ * @param col The column index of the block where the move was made
+ * @param player The player who made the move
+ */
+ public void recordMove(int row, int col, Player player) {
+ moveHistory.push(new Move(row, col, player));
+ }
+
+ /**
+ * Inner class to represent a move made by a player.
+ */
+ private static class Move {
+ private int row;
+ private int col;
+ private Player player;
+
+ public Move(int row, int col, Player player) {
+ this.row = row;
+ this.col = col;
+ this.player = player;
+ }
+
+ public int getRow() {
+ return row;
+ }
+
+ public int getCol() {
+ return col;
+ }
+
+ public Player getPlayer() {
+ return player;
+ }
}
-}
+}
\ No newline at end of file
diff --git a/tictactoe/src/view/GameBoardView.java b/tictactoe/src/view/GameBoardView.java
index 44c17d67..875a1e6d 100644
--- a/tictactoe/src/view/GameBoardView.java
+++ b/tictactoe/src/view/GameBoardView.java
@@ -9,33 +9,31 @@
import javax.swing.JButton;
import javax.swing.JPanel;
-
/**
* The GameBoardView class visualizes the game board of blocks.
*
- * NOTE) For the Composite design pattern, this class is-a Component (i.e. View).
+ * NOTE) For the Composite design pattern, this class is-a Component (i.e.
+ * View).
*/
-public class GameBoardView implements View
-{
- private JButton[][] blocks = new JButton[3][3];
+public class GameBoardView implements View {
+ public JButton[][] blocks = new JButton[3][3];
-
public GameBoardView(JPanel game, RowGameController controller) {
- super();
+ super();
// Initialize a JButton for each cell of the 3x3 game board.
- for(int row = 0; row<3; row++) {
- for(int column = 0; column<3 ;column++) {
+ for (int row = 0; row < 3; row++) {
+ for (int column = 0; column < 3; column++) {
blocks[row][column] = new JButton();
- blocks[row][column].setPreferredSize(new Dimension(75,75));
+ blocks[row][column].setPreferredSize(new Dimension(75, 75));
game.add(blocks[row][column]);
blocks[row][column].addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
- controller.move((JButton)e.getSource());
+ controller.move((JButton) e.getSource());
}
});
}
- }
+ }
}
/**
@@ -47,37 +45,37 @@ public void actionPerformed(ActionEvent e) {
* if it is part of this game board and null otherwise
*/
public BlockIndex getBlockIndex(JButton block) {
- for (int row = 0; row < 3; row++) {
- for (int column = 0; column < 3; column++) {
- if (this.blocks[row][column] == block) {
- // Found
- return new BlockIndex(row, column);
- }
- } // end for column
- } // end for row
+ for (int row = 0; row < 3; row++) {
+ for (int column = 0; column < 3; column++) {
+ if (this.blocks[row][column] == block) {
+ // Found
+ return new BlockIndex(row, column);
+ }
+ } // end for column
+ } // end for row
- // Not found
- return null;
+ // Not found
+ return null;
}
-
+
/**
- * Updates the block at the given row and column
+ * Updates the block at the given row and column
* after one of the player's moves.
*
* @param gameModel The RowGameModel containing the block
- * @param row The row that contains the block
- * @param column The column that contains the block
+ * @param row The row that contains the block
+ * @param column The column that contains the block
*/
public void updateBlock(RowGameModel gameModel, int row, int column) {
blocks[row][column].setText(gameModel.blocksData[row][column].getContents());
blocks[row][column].setEnabled(gameModel.blocksData[row][column].getIsLegalMove());
}
-
+
public void update(RowGameModel model) {
- for (int row = 0; row < 3; row++) {
- for (int column = 0; column < 3; column++) {
- updateBlock(model, row, column);
- } // end for col
- } // end for row
+ for (int row = 0; row < 3; row++) {
+ for (int column = 0; column < 3; column++) {
+ updateBlock(model, row, column);
+ } // end for col
+ } // end for row
}
} // end for GameBoardView
diff --git a/tictactoe/src/view/RowGameGUI.java b/tictactoe/src/view/RowGameGUI.java
index b9716d55..60fce794 100644
--- a/tictactoe/src/view/RowGameGUI.java
+++ b/tictactoe/src/view/RowGameGUI.java
@@ -19,11 +19,12 @@
public class RowGameGUI implements View {
public JFrame gui = new JFrame("Tic Tac Toe");
public RowGameModel gameModel = new RowGameModel();
- private GameBoardView gameBoardView;
+ public GameBoardView gameBoardView;
/** For the Composite design pattern, the RowGameGUI is the Composite */
private List viewList = new ArrayList();
public JButton reset = new JButton("Reset");
-
+ // Add a new button to the GUI for undo functionality
+ public JButton undo = new JButton("Undo");
/**
* Creates a new game initializing the GUI.
@@ -34,11 +35,22 @@ public RowGameGUI(RowGameController controller) {
gui.setResizable(true);
JPanel gamePanel = new JPanel(new FlowLayout());
- JPanel game = new JPanel(new GridLayout(3,3));
+ JPanel game = new JPanel(new GridLayout(3, 3));
gamePanel.add(game, BorderLayout.CENTER);
JPanel options = new JPanel(new FlowLayout());
options.add(reset);
+
+ // add the undo button to the options panel
+ options.add(undo);
+
+ // add action listener to the undo button
+ undo.addActionListener(new ActionListener() {
+ public void actionPerformed(ActionEvent e) {
+ controller.undoMove();
+ }
+ });
+
JPanel messages = new JPanel(new FlowLayout());
messages.setBackground(Color.white);
@@ -46,8 +58,8 @@ public RowGameGUI(RowGameController controller) {
gui.add(options, BorderLayout.CENTER);
gui.add(messages, BorderLayout.SOUTH);
- GameStatusView gameStatusView = new GameStatusView(messages);
- addView(gameStatusView);
+ GameStatusView gameStatusView = new GameStatusView(messages);
+ addView(gameStatusView);
reset.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
@@ -55,30 +67,30 @@ public void actionPerformed(ActionEvent e) {
}
});
- this.gameBoardView = new GameBoardView(game, controller);
- addView(this.gameBoardView);
+ this.gameBoardView = new GameBoardView(game, controller);
+ addView(this.gameBoardView);
}
public BlockIndex getBlockIndex(JButton block) {
- return this.gameBoardView.getBlockIndex(block);
+ return this.gameBoardView.getBlockIndex(block);
}
public void addView(View view) {
- // For the Composite API
-
- // Perform input validation
- if (view == null) {
- throw new IllegalArgumentException("The view must be non-null.");
- }
-
- this.viewList.add(view);
+ // For the Composite API
+
+ // Perform input validation
+ if (view == null) {
+ throw new IllegalArgumentException("The view must be non-null.");
+ }
+
+ this.viewList.add(view);
}
public void update(RowGameModel model) {
- // For the Composite API
-
- for (View currentView : this.viewList) {
- currentView.update(model);
- } // end for currentView
+ // For the Composite API
+
+ for (View currentView : this.viewList) {
+ currentView.update(model);
+ } // end for currentView
}
-}
+}
\ No newline at end of file
diff --git a/tictactoe/test/TestExample.java b/tictactoe/test/TestExample.java
index f25efecc..d19bef1e 100644
--- a/tictactoe/test/TestExample.java
+++ b/tictactoe/test/TestExample.java
@@ -3,34 +3,130 @@
import org.junit.Test;
import static org.junit.Assert.*;
+import javax.swing.JButton;
+
import model.Player;
import model.RowBlockModel;
import controller.RowGameController;
-/**
- * An example test class, which merely shows how to write JUnit tests.
- */
public class TestExample {
private RowGameController game;
@Before
public void setUp() {
- game = new RowGameController();
+ game = new RowGameController();
}
@After
public void tearDown() {
- game = null;
+ game = null;
}
@Test
public void testNewGame() {
- assertEquals (Player.PLAYER_1, game.gameModel.getPlayer());
- assertEquals (9, game.gameModel.movesLeft);
+ assertEquals(Player.PLAYER_1, game.gameModel.getPlayer());
+ assertEquals(9, game.gameModel.movesLeft);
}
@Test(expected = IllegalArgumentException.class)
public void testNewBlockViolatesPrecondition() {
- RowBlockModel block = new RowBlockModel(null);
+ RowBlockModel block = new RowBlockModel(null);
}
+
+ @Test
+ public void testIllegalMove() {
+ // Make an illegal move (selecting an already occupied block)
+ // a legal move
+ game.move(game.gameView.gameBoardView.blocks[0][0]);
+ assertEquals(Player.PLAYER_2, game.gameModel.getPlayer());
+ assertEquals(8, game.gameModel.movesLeft);
+ // an illegal move (selecting an already occupied block)
+ game.move(game.gameView.gameBoardView.blocks[0][0]);
+ assertEquals(Player.PLAYER_1, game.gameModel.getPlayer());
+ assertEquals(7, game.gameModel.movesLeft);
+ }
+
+ @Test
+ public void testLegalMoveUpdatesGame() {
+
+ // Move to a valid block
+ game.move(game.gameView.gameBoardView.blocks[0][0]);
+
+ // The current player should have changed
+ assertEquals(Player.PLAYER_2, game.gameModel.getPlayer());
+
+ // The blocks data should have been updated
+ assertEquals("X", game.gameModel.blocksData[0][0].getContents());
+
+ // The number of moves left should have decreased by 1
+ assertEquals(8, game.gameModel.movesLeft);
+ }
+
+ @Test
+ public void testWinningMove() {
+ // Player 1 makes the winning move
+ game.move(game.gameView.gameBoardView.blocks[0][0]);
+ game.move(game.gameView.gameBoardView.blocks[0][1]);
+ game.move(game.gameView.gameBoardView.blocks[1][0]);
+ game.move(game.gameView.gameBoardView.blocks[0][2]);
+ game.move(game.gameView.gameBoardView.blocks[2][0]);
+
+ assertEquals("Player 1 wins!", game.gameModel.getFinalResult());
+ // assertEquals(Player.PLAYER_2, game.gameModel.getPlayer());
+ // The game should be over
+ assertEquals(false, game.gameModel.blocksData[0][2].getIsLegalMove());
+ }
+
+ @Test
+ public void testTieGame() {
+ // Make a series of moves that results in a tie game
+ game.move(game.gameView.gameBoardView.blocks[0][0]); // Player 1
+ game.move(game.gameView.gameBoardView.blocks[0][1]); // Player 2
+ game.move(game.gameView.gameBoardView.blocks[0][2]); // Player 1
+ game.move(game.gameView.gameBoardView.blocks[2][2]); // Player 2
+ game.move(game.gameView.gameBoardView.blocks[2][1]); // Player 1
+ game.move(game.gameView.gameBoardView.blocks[2][0]); // Player 2
+ game.move(game.gameView.gameBoardView.blocks[1][0]); // Player 1
+ game.move(game.gameView.gameBoardView.blocks[1][1]); // Player 2
+ game.move(game.gameView.gameBoardView.blocks[1][2]); // Player 1
+ // System.out.printf("%s", game.gameModel.getFinalResult());
+
+ assertEquals("Game ends in a draw", game.gameModel.getFinalResult());
+ }
+
+ @Test
+ public void testResetGame() {
+ // Reset the game and check if the initial configuration is as expected
+ game.resetGame();
+ assertEquals(Player.PLAYER_1, game.gameModel.getPlayer());
+ assertEquals(9, game.gameModel.movesLeft);
+ // The game should not be over
+ assertEquals(true, game.gameModel.blocksData[0][2].getIsLegalMove());
+ assertNull(game.gameModel.getFinalResult());
+ }
+
+ @Test
+ public void testUndoNotAllowedBeforeMove() {
+ // Undo should not be allowed if no moves have been made
+ game.undoMove();
+ }
+
+ @Test
+ public void testUndoMove() {
+
+ // Make a move
+ game.move(game.gameView.gameBoardView.blocks[0][0]);
+
+ // Verify the move was made successfully
+ assertEquals(Player.PLAYER_2, game.gameModel.getPlayer());
+ assertEquals(8, game.gameModel.movesLeft);
+
+ // Undo the move
+ game.undoMove();
+
+ // Verify the game is updated appropriately
+ assertEquals(Player.PLAYER_1, game.gameModel.getPlayer());
+ assertEquals(9, game.gameModel.movesLeft);
+ }
+
}