Repository files navigation

Step 1: Setting up the IntelliJ IDE - using jdk21

I wasn't able to configure at first This blog helped me out: https://www.jetbrains.com/help/idea/creating-and-running-your-first-java-application.html#run_app

Step 2: I watched the video and coded side by side Writing very bad code at first for simulation a game result for tic tac toe

PART 2:

Step 3: Do refactoring and restructuring of the code.

Issue faced = @e get an error while accessing: board1.cells[i][0];

Above issue ensures that we could not make changes to underlying data structures and have to make restriction on how we want others to make changes. ie creating getCell method to access cell at i,j;

Step 4: We need to adhere to the Single Responsibility principle now: (changed Move method and converted Board to abstract class with abstract move method)

While doing Step 4, I learned these two things:

  1. When to use extend and when to use implements in the Java ?
  2. What are abstract methods and classes and when to use them ?

Outcome: Game Engine => Responsibility => Any changes in the board, we come here (Like different moves or different board configuration) Rule Engine => Responsibility => Make sure that rules are followed in the game AI Player => Responsibility => Suggestion Moves

Step 5: I got into the problem of testing the code again and again using manual testing. There-fore decided to write the unit test cases to validate my changes.

While doing Step 5, I learned these things:

  1. Unit Test cases are important for quick validation of logic, in fact I found 2 bugs while doing unit testing
  2. Unit Test should be readable and extensible so that we don't need to rewrite our tests again

Step 6: Open CLose Principle : Our system should be open to extension but close to modification

What we are doing in this: We want to have optimised suggestMove function but instead of changing in the Main file, we are extending the suggestMove function to incorporate smart and simple move

While doing Step 6, I learned these things:

  1. We should not write such code which forces us to make changes in the callers or main functions which are already tested.
  2. While modifying anything , we create a wrapper over already tested code instead of modifying it.
  3. Smartly think of handling concurrent request without causing deadlock (Ex here is if we wanted to undo the suggested move , then high possibility is that parallel request can create deadlocks)

Step 7: Making tests extensible, we now don't rely on AiEngine to suggest move, as our main focus is to test the moves and rules.

Step 8: Using Prototype Design Pattern: It is used when we wanted to deep or shallow clone the object. It is beneficial when new Object creation is expensive

Step 9: We used Lambda functions to adhere to the DRY principle.

Step 10: Making Code Extensible Using the Open-Closed Principle

Key Points:

  1. Our RuleEngine evaluates multiple scenarios to determine the game state. Each scenario is represented as a Rule.
  2. Initially, adding a new rule required modifying the getState function, making the approach inflexible and violating the Open-Closed Principle.
  3. To enhance extensibility, we introduced a Rule class and a set of rules that can be dynamically added to the RuleEngine via its constructor.
  4. This design allows new rules to be incorporated without modifying existing logic, making the system more scalable and maintainable.

About

An extensible game engine that can play tic tac toe and is extensible to any kind of Board Game

Topics

Resources

Stars

0 stars

Watchers

1 watching

Forks

Releases

Packages

Used by

Contributors

Languages

, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Add copy buttons to all
 blocks\n(function() {\n function addCopyButtons() {\n document.querySelectorAll('pre code').forEach(function(codeBlock) {\n if (codeBlock.parentElement.hasAttribute('data-copy-added')) return;\n codeBlock.parentElement.setAttribute('data-copy-added', 'true');\n \n var btn = document.createElement('button');\n btn.textContent = 'Copy';\n btn.style.cssText = 'position:absolute;top:4px;right:4px;padding:2px 8px;font-size:11px;background:#4ecdc4;border:none;border-radius:4px;color:#1a1a2e;cursor:pointer;opacity:0.7;transition:opacity 0.2s;';\n btn.onmouseover = function() { this.style.opacity = '1'; };\n btn.onmouseout = function() { this.style.opacity = '0.7'; };\n btn.onclick = function() {\n navigator.clipboard.writeText(codeBlock.textContent).then(function() {\n btn.textContent = 'Copied!';\n setTimeout(function() { btn.textContent = 'Copy'; }, 1500);\n });\n };\n codeBlock.parentElement.style.position = 'relative';\n codeBlock.parentElement.appendChild(btn);\n });\n }\n \n addCopyButtons();\n \n // Re-run on dynamic content\n var observer = new MutationObserver(addCopyButtons);\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "Add Copy Buttons to Code Blocks");
}
} catch(__e) { console.warn('[Userscript:Add Copy Buttons to Code Blocks]', __e); }
})();
(function(){
try {
var __m = "github.com";
var __re = new RegExp('^' + "github\\.com" + '
Skip to content

Repository files navigation

Step 1: Setting up the IntelliJ IDE - using jdk21

I wasn't able to configure at first This blog helped me out: https://www.jetbrains.com/help/idea/creating-and-running-your-first-java-application.html#run_app

Step 2: I watched the video and coded side by side Writing very bad code at first for simulation a game result for tic tac toe

PART 2:

Step 3: Do refactoring and restructuring of the code.

Issue faced = @e get an error while accessing: board1.cells[i][0];

Above issue ensures that we could not make changes to underlying data structures and have to make restriction on how we want others to make changes. ie creating getCell method to access cell at i,j;

Step 4: We need to adhere to the Single Responsibility principle now: (changed Move method and converted Board to abstract class with abstract move method)

While doing Step 4, I learned these two things:

  1. When to use extend and when to use implements in the Java ?
  2. What are abstract methods and classes and when to use them ?

Outcome: Game Engine => Responsibility => Any changes in the board, we come here (Like different moves or different board configuration) Rule Engine => Responsibility => Make sure that rules are followed in the game AI Player => Responsibility => Suggestion Moves

Step 5: I got into the problem of testing the code again and again using manual testing. There-fore decided to write the unit test cases to validate my changes.

While doing Step 5, I learned these things:

  1. Unit Test cases are important for quick validation of logic, in fact I found 2 bugs while doing unit testing
  2. Unit Test should be readable and extensible so that we don't need to rewrite our tests again

Step 6: Open CLose Principle : Our system should be open to extension but close to modification

What we are doing in this: We want to have optimised suggestMove function but instead of changing in the Main file, we are extending the suggestMove function to incorporate smart and simple move

While doing Step 6, I learned these things:

  1. We should not write such code which forces us to make changes in the callers or main functions which are already tested.
  2. While modifying anything , we create a wrapper over already tested code instead of modifying it.
  3. Smartly think of handling concurrent request without causing deadlock (Ex here is if we wanted to undo the suggested move , then high possibility is that parallel request can create deadlocks)

Step 7: Making tests extensible, we now don't rely on AiEngine to suggest move, as our main focus is to test the moves and rules.

Step 8: Using Prototype Design Pattern: It is used when we wanted to deep or shallow clone the object. It is beneficial when new Object creation is expensive

Step 9: We used Lambda functions to adhere to the DRY principle.

Step 10: Making Code Extensible Using the Open-Closed Principle

Key Points:

  1. Our RuleEngine evaluates multiple scenarios to determine the game state. Each scenario is represented as a Rule.
  2. Initially, adding a new rule required modifying the getState function, making the approach inflexible and violating the Open-Closed Principle.
  3. To enhance extensibility, we introduced a Rule class and a set of rules that can be dynamically added to the RuleEngine via its constructor.
  4. This design allows new rules to be incorporated without modifying existing logic, making the system more scalable and maintainable.

About

An extensible game engine that can play tic tac toe and is extensible to any kind of Board Game

Topics

Resources

Stars

0 stars

Watchers

1 watching

Forks

Releases

Packages

Used by

Contributors

Languages

, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Force GitHub README to respect dark mode\n(function() {\n var style = document.createElement('style');\n style.textContent = '\n .markdown-body {\n color-scheme: dark light;\n }\n .markdown-body pre { background: #161b22 !important; }\n .markdown-body code { background: rgba(110, 118, 129, 0.4) !important; }\n .markdown-body table th, .markdown-body table td { border-color: #30363d !important; }\n .markdown-body img { background: #0d1117; }\n .markdown-body blockquote { border-left-color: #8b949e; }\n .markdown-body hr { border-color: #30363d; }\n ';\n document.head.appendChild(style);\n})();", "GitHub Dark Mode README Fix"); } } catch(__e) { console.warn('[Userscript:GitHub Dark Mode README Fix]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content

Repository files navigation

Step 1: Setting up the IntelliJ IDE - using jdk21

I wasn't able to configure at first This blog helped me out: https://www.jetbrains.com/help/idea/creating-and-running-your-first-java-application.html#run_app

Step 2: I watched the video and coded side by side Writing very bad code at first for simulation a game result for tic tac toe

PART 2:

Step 3: Do refactoring and restructuring of the code.

Issue faced = @e get an error while accessing: board1.cells[i][0];

Above issue ensures that we could not make changes to underlying data structures and have to make restriction on how we want others to make changes. ie creating getCell method to access cell at i,j;

Step 4: We need to adhere to the Single Responsibility principle now: (changed Move method and converted Board to abstract class with abstract move method)

While doing Step 4, I learned these two things:

  1. When to use extend and when to use implements in the Java ?
  2. What are abstract methods and classes and when to use them ?

Outcome: Game Engine => Responsibility => Any changes in the board, we come here (Like different moves or different board configuration) Rule Engine => Responsibility => Make sure that rules are followed in the game AI Player => Responsibility => Suggestion Moves

Step 5: I got into the problem of testing the code again and again using manual testing. There-fore decided to write the unit test cases to validate my changes.

While doing Step 5, I learned these things:

  1. Unit Test cases are important for quick validation of logic, in fact I found 2 bugs while doing unit testing
  2. Unit Test should be readable and extensible so that we don't need to rewrite our tests again

Step 6: Open CLose Principle : Our system should be open to extension but close to modification

What we are doing in this: We want to have optimised suggestMove function but instead of changing in the Main file, we are extending the suggestMove function to incorporate smart and simple move

While doing Step 6, I learned these things:

  1. We should not write such code which forces us to make changes in the callers or main functions which are already tested.
  2. While modifying anything , we create a wrapper over already tested code instead of modifying it.
  3. Smartly think of handling concurrent request without causing deadlock (Ex here is if we wanted to undo the suggested move , then high possibility is that parallel request can create deadlocks)

Step 7: Making tests extensible, we now don't rely on AiEngine to suggest move, as our main focus is to test the moves and rules.

Step 8: Using Prototype Design Pattern: It is used when we wanted to deep or shallow clone the object. It is beneficial when new Object creation is expensive

Step 9: We used Lambda functions to adhere to the DRY principle.

Step 10: Making Code Extensible Using the Open-Closed Principle

Key Points:

  1. Our RuleEngine evaluates multiple scenarios to determine the game state. Each scenario is represented as a Rule.
  2. Initially, adding a new rule required modifying the getState function, making the approach inflexible and violating the Open-Closed Principle.
  3. To enhance extensibility, we introduced a Rule class and a set of rules that can be dynamically added to the RuleEngine via its constructor.
  4. This design allows new rules to be incorporated without modifying existing logic, making the system more scalable and maintainable.

About

An extensible game engine that can play tic tac toe and is extensible to any kind of Board Game

Topics

Resources

Stars

0 stars

Watchers

1 watching

Forks

Releases

Packages

Used by

Contributors

Languages

, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Highlight search terms from Google/DuckDuckGo/Bing referrer\n(function() {\n var ref = document.referrer;\n var terms = [];\n \n if (ref.includes('google.com') || ref.includes('duckduckgo.com') || ref.includes('bing.com')) {\n var url = new URL(ref);\n var q = url.searchParams.get('q') || url.searchParams.get('p');\n if (q) {\n terms = q.split(/\\s+/).filter(function(t) { return t.length > 2; });\n }\n }\n \n if (terms.length === 0) return;\n \n var style = document.createElement('style');\n style.textContent = '.userscript-highlight { background: #fbbf24; color: #1a1a2e; padding: 1px 3px; border-radius: 2px; }';\n document.head.appendChild(style);\n \n function highlight(node) {\n if (node.nodeType === 3) { // text node\n var text = node.textContent;\n var found = false;\n terms.forEach(function(term) {\n var regex = new RegExp('(' + term.replace(/[.*+?^${}()|[\\]\\\\]/g, '\\\\') + ')', 'gi');\n if (regex.test(text)) {\n found = true;\n var frag = document.createDocumentFragment();\n var parts = text.split(regex);\n parts.forEach(function(part, i) {\n if (i % 2 === 0) {\n frag.appendChild(document.createTextNode(part));\n } else {\n var span = document.createElement('span');\n span.className = 'userscript-highlight';\n span.textContent = part;\n frag.appendChild(span);\n }\n });\n node.parentNode.replaceChild(frag, node);\n }\n });\n } else if (node.nodeType === 1 && node.childNodes) { // element\n var skipTags = ['SCRIPT', 'STYLE', 'NOSCRIPT', 'TEXTAREA', 'INPUT', 'SELECT'];\n if (!skipTags.includes(node.tagName)) {\n Array.from(node.childNodes).forEach(highlight);\n }\n }\n }\n \n highlight(document.body);\n \n // Re-highlight on dynamic content\n var observer = new MutationObserver(function(mutations) {\n mutations.forEach(function(m) {\n m.addedNodes.forEach(function(node) {\n if (node.nodeType === 1 || node.nodeType === 3) highlight(node);\n });\n });\n });\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "Highlight Search Terms"); } } catch(__e) { console.warn('[Userscript:Highlight Search Terms]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content

Repository files navigation

Step 1: Setting up the IntelliJ IDE - using jdk21

I wasn't able to configure at first This blog helped me out: https://www.jetbrains.com/help/idea/creating-and-running-your-first-java-application.html#run_app

Step 2: I watched the video and coded side by side Writing very bad code at first for simulation a game result for tic tac toe

PART 2:

Step 3: Do refactoring and restructuring of the code.

Issue faced = @e get an error while accessing: board1.cells[i][0];

Above issue ensures that we could not make changes to underlying data structures and have to make restriction on how we want others to make changes. ie creating getCell method to access cell at i,j;

Step 4: We need to adhere to the Single Responsibility principle now: (changed Move method and converted Board to abstract class with abstract move method)

While doing Step 4, I learned these two things:

  1. When to use extend and when to use implements in the Java ?
  2. What are abstract methods and classes and when to use them ?

Outcome: Game Engine => Responsibility => Any changes in the board, we come here (Like different moves or different board configuration) Rule Engine => Responsibility => Make sure that rules are followed in the game AI Player => Responsibility => Suggestion Moves

Step 5: I got into the problem of testing the code again and again using manual testing. There-fore decided to write the unit test cases to validate my changes.

While doing Step 5, I learned these things:

  1. Unit Test cases are important for quick validation of logic, in fact I found 2 bugs while doing unit testing
  2. Unit Test should be readable and extensible so that we don't need to rewrite our tests again

Step 6: Open CLose Principle : Our system should be open to extension but close to modification

What we are doing in this: We want to have optimised suggestMove function but instead of changing in the Main file, we are extending the suggestMove function to incorporate smart and simple move

While doing Step 6, I learned these things:

  1. We should not write such code which forces us to make changes in the callers or main functions which are already tested.
  2. While modifying anything , we create a wrapper over already tested code instead of modifying it.
  3. Smartly think of handling concurrent request without causing deadlock (Ex here is if we wanted to undo the suggested move , then high possibility is that parallel request can create deadlocks)

Step 7: Making tests extensible, we now don't rely on AiEngine to suggest move, as our main focus is to test the moves and rules.

Step 8: Using Prototype Design Pattern: It is used when we wanted to deep or shallow clone the object. It is beneficial when new Object creation is expensive

Step 9: We used Lambda functions to adhere to the DRY principle.

Step 10: Making Code Extensible Using the Open-Closed Principle

Key Points:

  1. Our RuleEngine evaluates multiple scenarios to determine the game state. Each scenario is represented as a Rule.
  2. Initially, adding a new rule required modifying the getState function, making the approach inflexible and violating the Open-Closed Principle.
  3. To enhance extensibility, we introduced a Rule class and a set of rules that can be dynamically added to the RuleEngine via its constructor.
  4. This design allows new rules to be incorporated without modifying existing logic, making the system more scalable and maintainable.

About

An extensible game engine that can play tic tac toe and is extensible to any kind of Board Game

Topics

Resources

Stars

0 stars

Watchers

1 watching

Forks

Releases

Packages

Used by

Contributors

Languages

, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Strip utm_, fbclid, gclid, etc. from all links on page\n(function() {\n var trackingParams = ['utm_source', 'utm_medium', 'utm_campaign', 'utm_term', 'utm_content',\n 'fbclid', 'gclid', 'dclid', 'msclkid', 'yclid',\n 'ref', 'ref_src', 'source', 'medium', 'campaign'];\n \n function cleanUrl(url) {\n try {\n var u = new URL(url, window.location.origin);\n var changed = false;\n trackingParams.forEach(function(p) {\n if (u.searchParams.has(p)) {\n u.searchParams.delete(p);\n changed = true;\n }\n });\n return changed ? u.toString() : url;\n } catch (e) {\n return url;\n }\n }\n \n function cleanLinks() {\n document.querySelectorAll('a[href]').forEach(function(a) {\n var clean = cleanUrl(a.href);\n if (clean !== a.href) a.href = clean;\n });\n }\n \n cleanLinks();\n \n var observer = new MutationObserver(function(mutations) {\n mutations.forEach(function(m) {\n m.addedNodes.forEach(function(node) {\n if (node.nodeType === 1) {\n if (node.tagName === 'A') cleanLinks();\n node.querySelectorAll('a[href]').forEach(function(a) {\n var clean = cleanUrl(a.href);\n if (clean !== a.href) a.href = clean;\n });\n }\n });\n });\n });\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "Remove Tracking Parameters from Links"); } } catch(__e) { console.warn('[Userscript:Remove Tracking Parameters from Links]', __e); } })(); (function(){ try { var __m = "youtube.com"; var __re = new RegExp('^' + "youtube\\.com" + '
Skip to content

Repository files navigation

Step 1: Setting up the IntelliJ IDE - using jdk21

I wasn't able to configure at first This blog helped me out: https://www.jetbrains.com/help/idea/creating-and-running-your-first-java-application.html#run_app

Step 2: I watched the video and coded side by side Writing very bad code at first for simulation a game result for tic tac toe

PART 2:

Step 3: Do refactoring and restructuring of the code.

Issue faced = @e get an error while accessing: board1.cells[i][0];

Above issue ensures that we could not make changes to underlying data structures and have to make restriction on how we want others to make changes. ie creating getCell method to access cell at i,j;

Step 4: We need to adhere to the Single Responsibility principle now: (changed Move method and converted Board to abstract class with abstract move method)

While doing Step 4, I learned these two things:

  1. When to use extend and when to use implements in the Java ?
  2. What are abstract methods and classes and when to use them ?

Outcome: Game Engine => Responsibility => Any changes in the board, we come here (Like different moves or different board configuration) Rule Engine => Responsibility => Make sure that rules are followed in the game AI Player => Responsibility => Suggestion Moves

Step 5: I got into the problem of testing the code again and again using manual testing. There-fore decided to write the unit test cases to validate my changes.

While doing Step 5, I learned these things:

  1. Unit Test cases are important for quick validation of logic, in fact I found 2 bugs while doing unit testing
  2. Unit Test should be readable and extensible so that we don't need to rewrite our tests again

Step 6: Open CLose Principle : Our system should be open to extension but close to modification

What we are doing in this: We want to have optimised suggestMove function but instead of changing in the Main file, we are extending the suggestMove function to incorporate smart and simple move

While doing Step 6, I learned these things:

  1. We should not write such code which forces us to make changes in the callers or main functions which are already tested.
  2. While modifying anything , we create a wrapper over already tested code instead of modifying it.
  3. Smartly think of handling concurrent request without causing deadlock (Ex here is if we wanted to undo the suggested move , then high possibility is that parallel request can create deadlocks)

Step 7: Making tests extensible, we now don't rely on AiEngine to suggest move, as our main focus is to test the moves and rules.

Step 8: Using Prototype Design Pattern: It is used when we wanted to deep or shallow clone the object. It is beneficial when new Object creation is expensive

Step 9: We used Lambda functions to adhere to the DRY principle.

Step 10: Making Code Extensible Using the Open-Closed Principle

Key Points:

  1. Our RuleEngine evaluates multiple scenarios to determine the game state. Each scenario is represented as a Rule.
  2. Initially, adding a new rule required modifying the getState function, making the approach inflexible and violating the Open-Closed Principle.
  3. To enhance extensibility, we introduced a Rule class and a set of rules that can be dynamically added to the RuleEngine via its constructor.
  4. This design allows new rules to be incorporated without modifying existing logic, making the system more scalable and maintainable.

About

An extensible game engine that can play tic tac toe and is extensible to any kind of Board Game

Topics

Resources

Stars

0 stars

Watchers

1 watching

Forks

Releases

Packages

Used by

Contributors

Languages

, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Auto-enable theater mode on YouTube\n(function() {\n function tryTheater() {\n var btn = document.querySelector('button[aria-label=\"Theater mode\"], ytd-player #player button[title=\"Theater mode\"]');\n if (btn && !btn.classList.contains('activated')) {\n btn.click();\n }\n }\n \n // Try immediately\n tryTheater();\n \n // Try after navigation (SPA)\n var lastUrl = location.href;\n setInterval(function() {\n if (location.href !== lastUrl) {\n lastUrl = location.href;\n setTimeout(tryTheater, 500);\n }\n }, 1000);\n \n // Also try on player load\n var observer = new MutationObserver(tryTheater);\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "YouTube Theater Mode Default"); } } catch(__e) { console.warn('[Userscript:YouTube Theater Mode Default]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content

Repository files navigation

Step 1: Setting up the IntelliJ IDE - using jdk21

I wasn't able to configure at first This blog helped me out: https://www.jetbrains.com/help/idea/creating-and-running-your-first-java-application.html#run_app

Step 2: I watched the video and coded side by side Writing very bad code at first for simulation a game result for tic tac toe

PART 2:

Step 3: Do refactoring and restructuring of the code.

Issue faced = @e get an error while accessing: board1.cells[i][0];

Above issue ensures that we could not make changes to underlying data structures and have to make restriction on how we want others to make changes. ie creating getCell method to access cell at i,j;

Step 4: We need to adhere to the Single Responsibility principle now: (changed Move method and converted Board to abstract class with abstract move method)

While doing Step 4, I learned these two things:

  1. When to use extend and when to use implements in the Java ?
  2. What are abstract methods and classes and when to use them ?

Outcome: Game Engine => Responsibility => Any changes in the board, we come here (Like different moves or different board configuration) Rule Engine => Responsibility => Make sure that rules are followed in the game AI Player => Responsibility => Suggestion Moves

Step 5: I got into the problem of testing the code again and again using manual testing. There-fore decided to write the unit test cases to validate my changes.

While doing Step 5, I learned these things:

  1. Unit Test cases are important for quick validation of logic, in fact I found 2 bugs while doing unit testing
  2. Unit Test should be readable and extensible so that we don't need to rewrite our tests again

Step 6: Open CLose Principle : Our system should be open to extension but close to modification

What we are doing in this: We want to have optimised suggestMove function but instead of changing in the Main file, we are extending the suggestMove function to incorporate smart and simple move

While doing Step 6, I learned these things:

  1. We should not write such code which forces us to make changes in the callers or main functions which are already tested.
  2. While modifying anything , we create a wrapper over already tested code instead of modifying it.
  3. Smartly think of handling concurrent request without causing deadlock (Ex here is if we wanted to undo the suggested move , then high possibility is that parallel request can create deadlocks)

Step 7: Making tests extensible, we now don't rely on AiEngine to suggest move, as our main focus is to test the moves and rules.

Step 8: Using Prototype Design Pattern: It is used when we wanted to deep or shallow clone the object. It is beneficial when new Object creation is expensive

Step 9: We used Lambda functions to adhere to the DRY principle.

Step 10: Making Code Extensible Using the Open-Closed Principle

Key Points:

  1. Our RuleEngine evaluates multiple scenarios to determine the game state. Each scenario is represented as a Rule.
  2. Initially, adding a new rule required modifying the getState function, making the approach inflexible and violating the Open-Closed Principle.
  3. To enhance extensibility, we introduced a Rule class and a set of rules that can be dynamically added to the RuleEngine via its constructor.
  4. This design allows new rules to be incorporated without modifying existing logic, making the system more scalable and maintainable.

About

An extensible game engine that can play tic tac toe and is extensible to any kind of Board Game

Topics

Resources

Stars

0 stars

Watchers

1 watching

Forks

Releases

Packages

Used by

Contributors

Languages

, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Remove or un-stick sticky/fixed headers that block content\n(function() {\n function unstick() {\n document.querySelectorAll('header, nav, [role=\"banner\"], .header, .navbar, .sticky, .fixed-top, [style*=\"position: fixed\"], [style*=\"position:sticky\"]').forEach(function(el) {\n if (el.style.position === 'fixed' || el.style.position === 'sticky' || \n getComputedStyle(el).position === 'fixed' || getComputedStyle(el).position === 'sticky') {\n el.style.position = 'static';\n el.style.top = 'auto';\n el.style.zIndex = 'auto';\n }\n });\n }\n \n unstick();\n \n var observer = new MutationObserver(unstick);\n observer.observe(document.body, { childList: true, subtree: true, attributes: true, attributeFilter: ['style', 'class'] });\n})();", "Kill Sticky Headers"); } } catch(__e) { console.warn('[Userscript:Kill Sticky Headers]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content

Repository files navigation

Step 1: Setting up the IntelliJ IDE - using jdk21

I wasn't able to configure at first This blog helped me out: https://www.jetbrains.com/help/idea/creating-and-running-your-first-java-application.html#run_app

Step 2: I watched the video and coded side by side Writing very bad code at first for simulation a game result for tic tac toe

PART 2:

Step 3: Do refactoring and restructuring of the code.

Issue faced = @e get an error while accessing: board1.cells[i][0];

Above issue ensures that we could not make changes to underlying data structures and have to make restriction on how we want others to make changes. ie creating getCell method to access cell at i,j;

Step 4: We need to adhere to the Single Responsibility principle now: (changed Move method and converted Board to abstract class with abstract move method)

While doing Step 4, I learned these two things:

  1. When to use extend and when to use implements in the Java ?
  2. What are abstract methods and classes and when to use them ?

Outcome: Game Engine => Responsibility => Any changes in the board, we come here (Like different moves or different board configuration) Rule Engine => Responsibility => Make sure that rules are followed in the game AI Player => Responsibility => Suggestion Moves

Step 5: I got into the problem of testing the code again and again using manual testing. There-fore decided to write the unit test cases to validate my changes.

While doing Step 5, I learned these things:

  1. Unit Test cases are important for quick validation of logic, in fact I found 2 bugs while doing unit testing
  2. Unit Test should be readable and extensible so that we don't need to rewrite our tests again

Step 6: Open CLose Principle : Our system should be open to extension but close to modification

What we are doing in this: We want to have optimised suggestMove function but instead of changing in the Main file, we are extending the suggestMove function to incorporate smart and simple move

While doing Step 6, I learned these things:

  1. We should not write such code which forces us to make changes in the callers or main functions which are already tested.
  2. While modifying anything , we create a wrapper over already tested code instead of modifying it.
  3. Smartly think of handling concurrent request without causing deadlock (Ex here is if we wanted to undo the suggested move , then high possibility is that parallel request can create deadlocks)

Step 7: Making tests extensible, we now don't rely on AiEngine to suggest move, as our main focus is to test the moves and rules.

Step 8: Using Prototype Design Pattern: It is used when we wanted to deep or shallow clone the object. It is beneficial when new Object creation is expensive

Step 9: We used Lambda functions to adhere to the DRY principle.

Step 10: Making Code Extensible Using the Open-Closed Principle

Key Points:

  1. Our RuleEngine evaluates multiple scenarios to determine the game state. Each scenario is represented as a Rule.
  2. Initially, adding a new rule required modifying the getState function, making the approach inflexible and violating the Open-Closed Principle.
  3. To enhance extensibility, we introduced a Rule class and a set of rules that can be dynamically added to the RuleEngine via its constructor.
  4. This design allows new rules to be incorporated without modifying existing logic, making the system more scalable and maintainable.

About

An extensible game engine that can play tic tac toe and is extensible to any kind of Board Game

Topics

Resources

Stars

0 stars

Watchers

1 watching

Forks

Releases

Packages

Used by

Contributors

Languages

, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Universal Dark Mode - works on any site\n(function() {\n var enabled = true;\n \n function applyDarkMode() {\n if (!enabled) return;\n \n // Create style element if it doesn't exist\n var style = document.getElementById('universal-dark-mode-style');\n if (!style) {\n style = document.createElement('style');\n style.id = 'universal-dark-mode-style';\n document.head.appendChild(style);\n }\n \n // Dark mode CSS - inverts colors but preserves images/video\n style.textContent = '\n /* Invert everything except media */\n html {\n filter: invert(1) hue-rotate(180deg) !important;\n background: #1a1a2e !important;\n }\n \n /* Restore images, videos, iframes, canvas */\n img, video, iframe, canvas, svg, picture, [style*=\"background-image\"] {\n filter: invert(1) hue-rotate(180deg) !important;\n }\n \n /* Preserve specific elements that should not be inverted */\n .no-dark-mode, .no-dark-mode *,\n [data-theme=\"light\"], [data-theme=\"light\"],\n .ace_editor, .ace_editor *,\n .CodeMirror, .CodeMirror *,\n .monaco-editor, .monaco-editor *,\n .markdown-body pre, .markdown-body pre *,\n .highlight, .highlight *,\n pre code, pre code * {\n filter: none !important;\n }\n \n /* Fix common UI elements */\n .modal, .popup, .dropdown-menu, .tooltip, .popover {\n filter: invert(1) hue-rotate(180deg) !important;\n background: #2d2d44 !important;\n border-color: #444 !important;\n }\n \n /* Scrollbars */\n ::-webkit-scrollbar { background: #1a1a2e !important; }\n ::-webkit-scrollbar-thumb { background: #444 !important; }\n ::-webkit-scrollbar-thumb:hover { background: #555 !important; }\n \n /* Selection */\n ::selection { background: #4ecdc4 !important; color: #1a1a2e !important; }\n ::-moz-selection { background: #4ecdc4 !important; color: #1a1a2e !important; }\n ';\n }\n \n function removeDarkMode() {\n var style = document.getElementById('universal-dark-mode-style');\n if (style) style.remove();\n }\n \n // Toggle with Alt+Shift+D\n document.addEventListener('keydown', function(e) {\n if (e.altKey && e.shiftKey && e.key === 'D') {\n e.preventDefault();\n enabled = !enabled;\n if (enabled) {\n applyDarkMode();\n console.log('[Universal Dark Mode] Enabled');\n } else {\n removeDarkMode();\n console.log('[Universal Dark Mode] Disabled');\n }\n }\n });\n \n // Apply on load\n applyDarkMode();\n \n // Re-apply on dynamic content\n var observer = new MutationObserver(function(mutations) {\n if (enabled && !document.getElementById('universal-dark-mode-style')) {\n applyDarkMode();\n }\n });\n observer.observe(document.head, { childList: true });\n \n console.log('[Universal Dark Mode] Loaded - Press Alt+Shift+D to toggle');\n})();", "Universal Dark Mode"); } } catch(__e) { console.warn('[Userscript:Universal Dark Mode]', __e); } })(); })();
Skip to content

Repository files navigation

Step 1: Setting up the IntelliJ IDE - using jdk21

I wasn't able to configure at first This blog helped me out: https://www.jetbrains.com/help/idea/creating-and-running-your-first-java-application.html#run_app

Step 2: I watched the video and coded side by side Writing very bad code at first for simulation a game result for tic tac toe

PART 2:

Step 3: Do refactoring and restructuring of the code.

Issue faced = @e get an error while accessing: board1.cells[i][0];

Above issue ensures that we could not make changes to underlying data structures and have to make restriction on how we want others to make changes. ie creating getCell method to access cell at i,j;

Step 4: We need to adhere to the Single Responsibility principle now: (changed Move method and converted Board to abstract class with abstract move method)

While doing Step 4, I learned these two things:

  1. When to use extend and when to use implements in the Java ?
  2. What are abstract methods and classes and when to use them ?

Outcome: Game Engine => Responsibility => Any changes in the board, we come here (Like different moves or different board configuration) Rule Engine => Responsibility => Make sure that rules are followed in the game AI Player => Responsibility => Suggestion Moves

Step 5: I got into the problem of testing the code again and again using manual testing. There-fore decided to write the unit test cases to validate my changes.

While doing Step 5, I learned these things:

  1. Unit Test cases are important for quick validation of logic, in fact I found 2 bugs while doing unit testing
  2. Unit Test should be readable and extensible so that we don't need to rewrite our tests again

Step 6: Open CLose Principle : Our system should be open to extension but close to modification

What we are doing in this: We want to have optimised suggestMove function but instead of changing in the Main file, we are extending the suggestMove function to incorporate smart and simple move

While doing Step 6, I learned these things:

  1. We should not write such code which forces us to make changes in the callers or main functions which are already tested.
  2. While modifying anything , we create a wrapper over already tested code instead of modifying it.
  3. Smartly think of handling concurrent request without causing deadlock (Ex here is if we wanted to undo the suggested move , then high possibility is that parallel request can create deadlocks)

Step 7: Making tests extensible, we now don't rely on AiEngine to suggest move, as our main focus is to test the moves and rules.

Step 8: Using Prototype Design Pattern: It is used when we wanted to deep or shallow clone the object. It is beneficial when new Object creation is expensive

Step 9: We used Lambda functions to adhere to the DRY principle.

Step 10: Making Code Extensible Using the Open-Closed Principle

Key Points:

  1. Our RuleEngine evaluates multiple scenarios to determine the game state. Each scenario is represented as a Rule.
  2. Initially, adding a new rule required modifying the getState function, making the approach inflexible and violating the Open-Closed Principle.
  3. To enhance extensibility, we introduced a Rule class and a set of rules that can be dynamically added to the RuleEngine via its constructor.
  4. This design allows new rules to be incorporated without modifying existing logic, making the system more scalable and maintainable.

About

An extensible game engine that can play tic tac toe and is extensible to any kind of Board Game

Topics

Resources

Stars

0 stars

Watchers

1 watching

Forks

Releases

Packages

Used by

Contributors

Languages